Files
edr-platform/apps/edr-freight-web/portal/src/pages/settings/TabGeneralManager.tsx
2026-06-17 13:17:09 +03:00

166 lines
5.1 KiB
TypeScript

import { useMemo } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { Briefcase, CheckCircle2, Save, XCircle } from "lucide-react";
import {
Card,
Group,
Stack,
Title,
Text,
TextInput,
Button,
Grid,
} from "@mantine/core";
import { api } from "@/services/api";
import PhoneInput from "@/components/auth/PhoneInput";
import type { ProfileResponse } from "@/types/profile";
const schema = z.object({
generalManagerName: z.string().min(1, "GM name is required"),
generalManagerEmail: z.string().email("Invalid GM email"),
generalManagerPhone: z.string().min(1, "GM phone is required"),
generalManagerPhoneCountryCode: z.string().min(1, "Country code is required"),
});
type FormData = z.infer<typeof schema>;
function splitPhone(fullPhone?: string | null) {
if (!fullPhone) return { code: "+251", number: "" };
const match = fullPhone.match(/^(\+\d{1,3})(.*)$/);
if (match) return { code: match[1], number: match[2] };
return { code: "+251", number: fullPhone };
}
interface TabGeneralManagerProps {
profile: ProfileResponse;
mode?: "edit" | "onboarding";
onContinue?: () => void;
}
export default function TabGeneralManager({ profile, mode = "edit", onContinue }: TabGeneralManagerProps) {
const queryClient = useQueryClient();
const defaultValues = useMemo((): FormData => {
const phone = splitPhone(profile.generalManagerPhone);
return {
generalManagerName: profile.generalManagerName ?? "",
generalManagerEmail: profile.generalManagerEmail ?? "",
generalManagerPhone: phone.number,
generalManagerPhoneCountryCode: phone.code,
};
}, [profile]);
const {
register,
handleSubmit,
reset,
formState: { errors, isDirty },
} = useForm<FormData>({
resolver: zodResolver(schema),
values: defaultValues,
});
const mutation = useMutation({
mutationFn: (data: FormData) =>
api.companies.updateProfile.call({
generalManagerName: data.generalManagerName,
generalManagerEmail: data.generalManagerEmail,
generalManagerPhone: `${data.generalManagerPhoneCountryCode}${data.generalManagerPhone}`,
}),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: api.companies.getProfile.queryKey() });
if (mode === "onboarding") onContinue?.();
},
});
const onSubmit = (data: FormData) => mutation.mutate(data);
return (
<Card padding="lg">
<Group gap="sm" mb="xs">
<Briefcase size={20} />
<Title order={3}>General Manager</Title>
</Group>
<Text c="edr-muted" size="sm" mb="lg">
Manage the general manager information
</Text>
<form onSubmit={handleSubmit(onSubmit)}>
<Stack gap="md">
<TextInput
label="Full Name"
placeholder="Abebe Bikila"
error={errors.generalManagerName?.message}
{...register("generalManagerName")}
/>
<Grid>
<Grid.Col span={6}>
<TextInput
label="Email Address"
type="email"
placeholder="gm@company.com"
error={errors.generalManagerEmail?.message}
{...register("generalManagerEmail")}
/>
</Grid.Col>
<Grid.Col span={6}>
<PhoneInput
countryCode={{ ...register("generalManagerPhoneCountryCode") }}
phone={{ ...register("generalManagerPhone"), placeholder: "912345678" }}
countryCodeError={errors.generalManagerPhoneCountryCode}
phoneError={errors.generalManagerPhone}
label="Phone Number"
/>
</Grid.Col>
</Grid>
</Stack>
<Group
justify="space-between"
mt="xl"
pt="md"
style={{ borderTop: "1px solid var(--mantine-color-edr-border-0)" }}
>
<Group gap="xs">
{mutation.isSuccess && (
<Group gap={6} c="green">
<CheckCircle2 size={16} />
<Text size="sm" fw={500}>Saved successfully</Text>
</Group>
)}
{mutation.isError && (
<Group gap={6} c="red">
<XCircle size={16} />
<Text size="sm" fw={500}>Save failed</Text>
</Group>
)}
</Group>
<Group gap="md">
{mode === "edit" && (
<Button
type="button"
variant="outline"
disabled={mutation.isPending || !isDirty}
onClick={() => reset()}
>
Reset
</Button>
)}
<Button
type="submit"
leftSection={<Save size={16} />}
loading={mutation.isPending}
>
{mode === "onboarding" ? "Continue" : "Save Changes"}
</Button>
</Group>
</Group>
</form>
</Card>
);
}