mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
166 lines
5.1 KiB
TypeScript
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>
|
|
);
|
|
}
|