271 lines
7.8 KiB
TypeScript
271 lines
7.8 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import {
|
|
View,
|
|
ScrollView,
|
|
Pressable,
|
|
TextInput,
|
|
ActivityIndicator,
|
|
useColorScheme,
|
|
} from "react-native";
|
|
import { useSirouRouter } from "@sirou/react-native";
|
|
import { AppRoutes } from "@/lib/routes";
|
|
import { Text } from "@/components/ui/text";
|
|
import { Button } from "@/components/ui/button";
|
|
import { ScreenWrapper } from "@/components/ScreenWrapper";
|
|
import { FormFlow } from "@/components/FormFlow";
|
|
import { api } from "@/lib/api";
|
|
import { toast } from "@/lib/toast-store";
|
|
import { getPlaceholderColor } from "@/lib/colors";
|
|
|
|
const STEPS = [
|
|
{ key: "basic", label: "Basic Info" },
|
|
{ key: "contact", label: "Contact" },
|
|
{ key: "address", label: "Address" },
|
|
];
|
|
|
|
export default function EditCompanyScreen() {
|
|
const nav = useSirouRouter<AppRoutes>();
|
|
const isDark = useColorScheme() === "dark";
|
|
const [step, setStep] = useState(0);
|
|
const [loading, setLoading] = useState(false);
|
|
const [saving, setSaving] = useState(false);
|
|
const [form, setForm] = useState({
|
|
name: "",
|
|
tin: "",
|
|
address: "",
|
|
city: "",
|
|
state: "",
|
|
zipCode: "",
|
|
country: "",
|
|
phone: "",
|
|
email: "",
|
|
website: "",
|
|
});
|
|
|
|
useEffect(() => {
|
|
const load = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await api.company.get();
|
|
const data = res?.data ?? res;
|
|
if (data) {
|
|
setForm({
|
|
name: data.name ?? "",
|
|
tin: data.tin ?? "",
|
|
address: data.address ?? "",
|
|
city: data.city ?? "",
|
|
state: data.state ?? "",
|
|
zipCode: data.zipCode ?? "",
|
|
country: data.country ?? "",
|
|
phone: data.phone ?? "",
|
|
email: data.email ?? "",
|
|
website: data.website ?? "",
|
|
});
|
|
}
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
load();
|
|
}, []);
|
|
|
|
const updateField = (key: keyof typeof form, value: string) => {
|
|
setForm((prev) => ({ ...prev, [key]: value }));
|
|
};
|
|
|
|
const handleNext = () => {
|
|
if (step === 0 && !form.name.trim()) {
|
|
toast.error("Required", "Company name is required");
|
|
return;
|
|
}
|
|
setStep(step + 1);
|
|
};
|
|
|
|
const handleSave = async () => {
|
|
if (!form.name.trim()) {
|
|
toast.error("Required", "Company name is required");
|
|
return;
|
|
}
|
|
|
|
setSaving(true);
|
|
try {
|
|
await api.company.update({ body: form });
|
|
toast.success("Saved", "Company information updated");
|
|
nav.back();
|
|
} catch (e: any) {
|
|
toast.error("Error", e?.message || "Failed to update company");
|
|
} finally {
|
|
setSaving(false);
|
|
}
|
|
};
|
|
|
|
if (loading) {
|
|
return (
|
|
<ScreenWrapper className="bg-background">
|
|
<View className="flex-1 items-center justify-center">
|
|
<ActivityIndicator color="#ea580c" size="large" />
|
|
</View>
|
|
</ScreenWrapper>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ScreenWrapper className="bg-background">
|
|
<FormFlow
|
|
steps={STEPS}
|
|
currentStep={step}
|
|
onNext={handleNext}
|
|
onBack={() => setStep(step - 1)}
|
|
onComplete={handleSave}
|
|
loading={saving}
|
|
completeLabel="Update Company"
|
|
>
|
|
{step === 0 && (
|
|
<View className="gap-5">
|
|
<Text className="text-[18px] font-sans-bold text-foreground tracking-tight">
|
|
Basic Information
|
|
</Text>
|
|
<View className="bg-card rounded-[6px] gap-4">
|
|
<Field
|
|
label="Company Name"
|
|
required
|
|
value={form.name}
|
|
placeholder="Enter company name"
|
|
onChangeText={(v) => updateField("name", v)}
|
|
/>
|
|
<Field
|
|
label="TIN"
|
|
value={form.tin}
|
|
placeholder="Tax Identification Number"
|
|
onChangeText={(v) => updateField("tin", v)}
|
|
/>
|
|
</View>
|
|
</View>
|
|
)}
|
|
|
|
{step === 1 && (
|
|
<View className="gap-5">
|
|
<Text className="text-[18px] font-sans-bold text-foreground tracking-tight">
|
|
Contact Information
|
|
</Text>
|
|
<View className="bg-card rounded-[6px] gap-4">
|
|
<Field
|
|
label="Phone"
|
|
value={form.phone}
|
|
placeholder="+1234567890"
|
|
onChangeText={(v) => updateField("phone", v)}
|
|
keyboardType="phone-pad"
|
|
/>
|
|
<Field
|
|
label="Email"
|
|
value={form.email}
|
|
placeholder="contact@company.com"
|
|
onChangeText={(v) => updateField("email", v)}
|
|
keyboardType="email-address"
|
|
/>
|
|
<Field
|
|
label="Website"
|
|
value={form.website}
|
|
placeholder="https://example.com"
|
|
onChangeText={(v) => updateField("website", v)}
|
|
/>
|
|
</View>
|
|
</View>
|
|
)}
|
|
|
|
{step === 2 && (
|
|
<View className="gap-5">
|
|
<Text className="text-[18px] font-sans-bold text-foreground tracking-tight">
|
|
Address
|
|
</Text>
|
|
<View className="bg-card rounded-[6px] gap-4">
|
|
<Field
|
|
label="Street Address"
|
|
value={form.address}
|
|
placeholder="123 Main Street"
|
|
onChangeText={(v) => updateField("address", v)}
|
|
/>
|
|
<View className="flex-row gap-4">
|
|
<View className="flex-1">
|
|
<Field
|
|
label="City"
|
|
value={form.city}
|
|
placeholder="New York"
|
|
onChangeText={(v) => updateField("city", v)}
|
|
/>
|
|
</View>
|
|
<View className="flex-1">
|
|
<Field
|
|
label="State"
|
|
value={form.state}
|
|
placeholder="NY"
|
|
onChangeText={(v) => updateField("state", v)}
|
|
/>
|
|
</View>
|
|
</View>
|
|
<View className="flex-row gap-4">
|
|
<View className="flex-1">
|
|
<Field
|
|
label="Zip Code"
|
|
value={form.zipCode}
|
|
placeholder="10001"
|
|
onChangeText={(v) => updateField("zipCode", v)}
|
|
keyboardType="number-pad"
|
|
/>
|
|
</View>
|
|
<View className="flex-1">
|
|
<Field
|
|
label="Country"
|
|
value={form.country}
|
|
placeholder="USA"
|
|
onChangeText={(v) => updateField("country", v)}
|
|
/>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
</View>
|
|
)}
|
|
</FormFlow>
|
|
</ScreenWrapper>
|
|
);
|
|
}
|
|
|
|
function Field({
|
|
label,
|
|
required,
|
|
value,
|
|
placeholder,
|
|
onChangeText,
|
|
keyboardType,
|
|
}: {
|
|
label: string;
|
|
required?: boolean;
|
|
value: string;
|
|
placeholder: string;
|
|
onChangeText: (v: string) => void;
|
|
keyboardType?: "default" | "email-address" | "phone-pad" | "number-pad";
|
|
}) {
|
|
const isDark = useColorScheme() === "dark";
|
|
return (
|
|
<View>
|
|
<Text className="text-xs font-sans-semibold mb-1.5 ml-1 text-foreground">
|
|
{label}
|
|
{required && <Text className="text-red-500"> *</Text>}
|
|
</Text>
|
|
<TextInput
|
|
className="h-11 px-3 rounded-[6px] border border-border text-foreground text-xs font-sans-medium"
|
|
style={{
|
|
backgroundColor: isDark ? "rgba(30,30,30,0.8)" : "rgba(241,245,249,0.2)",
|
|
}}
|
|
placeholder={placeholder}
|
|
placeholderTextColor={getPlaceholderColor(isDark)}
|
|
value={value}
|
|
onChangeText={onChangeText}
|
|
keyboardType={keyboardType || "default"}
|
|
autoCapitalize="none"
|
|
autoCorrect={false}
|
|
/>
|
|
</View>
|
|
);
|
|
}
|