Files
dashboard-noc-desa-darmasaba/src/routes/profile/edit.tsx

147 lines
3.4 KiB
TypeScript

import {
Button,
Card,
Container,
Divider,
Group,
Stack,
Text,
TextInput,
Title,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { IconChevronLeft, IconEdit } from "@tabler/icons-react";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { useState } from "react";
import { useSnapshot } from "valtio";
import { protectedRouteMiddleware } from "@/middleware/authMiddleware";
import { apiClient } from "@/utils/api-client";
import { authStore } from "../../store/auth";
export const Route = createFileRoute("/profile/edit")({
component: EditProfile,
beforeLoad: protectedRouteMiddleware,
onEnter({ context }) {
authStore.user = context?.user as any;
authStore.session = context?.session as any;
},
});
function EditProfile() {
const snap = useSnapshot(authStore);
const navigate = useNavigate();
const [isUpdating, setIsUpdating] = useState(false);
const form = useForm({
initialValues: {
name: snap.user?.name || "",
image: snap.user?.image || "",
},
validate: {
name: (value) =>
value.length < 2 ? "Name must have at least 2 letters" : null,
},
});
const handleUpdateProfile = async (values: typeof form.values) => {
try {
setIsUpdating(true);
const { data, error } = await apiClient.POST("/api/profile/update", {
body: values,
});
if (data?.user) {
authStore.user = {
...authStore.user,
...data.user,
} as any;
navigate({ to: "/profile" });
} else if (error) {
console.error("Update error:", error);
}
} catch (err) {
console.error("Failed to update profile:", err);
} finally {
setIsUpdating(false);
}
};
return (
<Container size="sm" py={50}>
<Stack gap="xl">
<Group justify="space-between" align="center">
<Box>
<Title order={1} c="#f3d5a3">
Edit Profil
</Title>
<Text c="dimmed" size="sm">
Perbarui informasi profil publik Anda
</Text>
</Box>
<Button
variant="subtle"
color="gray"
leftSection={<IconChevronLeft size={18} />}
onClick={() => navigate({ to: "/profile" })}
>
Kembali
</Button>
</Group>
<Divider color="rgba(251, 240, 223, 0.1)" />
<Card
withBorder
radius="md"
p="xl"
bg="rgba(26, 26, 26, 0.5)"
style={{ border: "1px solid rgba(251, 240, 223, 0.1)" }}
>
<form onSubmit={form.onSubmit(handleUpdateProfile)}>
<Stack gap="md">
<TextInput
label="Nama Lengkap"
placeholder="Masukkan nama lengkap Anda"
{...form.getInputProps("name")}
styles={{
label: { color: "#fbf0df", marginBottom: 8 },
input: {
backgroundColor: "rgba(0,0,0,0.2)",
color: "#fbf0df",
},
}}
/>
<TextInput
label="URL Foto Profil"
placeholder="https://example.com/photo.jpg"
{...form.getInputProps("image")}
styles={{
label: { color: "#fbf0df", marginBottom: 8 },
input: {
backgroundColor: "rgba(0,0,0,0.2)",
color: "#fbf0df",
},
}}
/>
<Button
type="submit"
fullWidth
mt="lg"
size="md"
color="orange"
loading={isUpdating}
leftSection={<IconEdit size={18} />}
>
Simpan Perubahan
</Button>
</Stack>
</form>
</Card>
</Stack>
</Container>
);
}
// Need Box from @mantine/core
import { Box } from "@mantine/core";