Pull Request branch dev-clone to main #1

Merged
gitea merged 429 commits from dev-clone into main 2024-12-23 09:31:34 +00:00
4 changed files with 158 additions and 160 deletions
Showing only changes of commit d3da289363 - Show all commits

View File

@ -16,17 +16,17 @@ import { respondents } from "../../drizzle/schema/respondents";
import { forbidden, notFound } from "../../errors/DashboardError"; import { forbidden, notFound } from "../../errors/DashboardError";
export const userFormSchema = z.object({ export const userFormSchema = z.object({
name: z.string().min(1, "Name is required").max(255), name: z.string().min(1, "Nama wajib diisi").max(255),
username: z.string().min(1, "Username is required").max(255), username: z.string().min(1, "Username wajib diisi").max(255),
email: z.string().min(1, "Email is required").max(255), email: z.string().min(1, "Email wajib diisi").max(255),
password: z.string().min(6, "Password is required"), password: z.string().min(6, "Password wajib diisi"),
companyName: z.string().min(1, "Company name is required").max(255), companyName: z.string().min(1, "Nama Perusahaan wajib diisi").max(255),
position: z.string().min(1, "Position is required").max(255), position: z.string().min(1, "Jabatan wajib diisi").max(255),
workExperience: z.string().min(1, "Work experience is required").max(255), workExperience: z.string().min(1, "Pengalaman Kerja wajib diisi").max(255),
address: z.string().min(1, "Address is required"), address: z.string().min(1, "Alamat wajib diisi"),
phoneNumber: z.string().min(1, "Phone number is required").max(13), phoneNumber: z.string().min(1, "Nomor Telepon wajib diisi").max(13),
isEnabled: z.string().default("false"), isEnabled: z.string().default("false"),
roles: z.array(z.string().min(1, "Role is required")), roles: z.array(z.string().min(1, "Role wajib diisi")),
}); });
export const userUpdateSchema = userFormSchema.extend({ export const userUpdateSchema = userFormSchema.extend({
@ -342,7 +342,7 @@ const usersRoute = new Hono<HonoEnv>()
.values({ .values({
companyName: userData.companyName, companyName: userData.companyName,
position: userData.position, position: userData.position,
workExperience: userData.workExperience, workExperience: userData.workExperience + " Tahun",
address: userData.address, address: userData.address,
phoneNumber: userData.phoneNumber, phoneNumber: userData.phoneNumber,
userId: newUser.id, userId: newUser.id,

View File

@ -1,5 +1,14 @@
import client from "@/honoClient"; import client from "@/honoClient";
import { Button, Flex, Modal, Text } from "@mantine/core"; import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/shadcn/components/ui/alert-dialog";
import { Button } from "@/shadcn/components/ui/button";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { getRouteApi, useSearch } from "@tanstack/react-router"; import { getRouteApi, useSearch } from "@tanstack/react-router";
import { deleteUser } from "../queries/userQueries"; import { deleteUser } from "../queries/userQueries";
@ -60,40 +69,34 @@ export default function UserDeleteModal() {
const isModalOpen = Boolean(searchParams.delete && userQuery.data); const isModalOpen = Boolean(searchParams.delete && userQuery.data);
return ( return (
<Modal <AlertDialog open={isModalOpen} onOpenChange={() => navigate({ search: {} })}>
opened={isModalOpen} <AlertDialogContent>
onClose={() => navigate({ search: {} })} <AlertDialogHeader>
title={`Konfirmasi Hapus`} <AlertDialogTitle>Konfirmasi Hapus</AlertDialogTitle>
> <AlertDialogDescription>
<Text size="sm">
Apakah Anda yakin ingin menghapus pengguna{" "} Apakah Anda yakin ingin menghapus pengguna{" "}
<Text span fw={700}> <strong>{userQuery.data?.name}</strong>?
{userQuery.data?.name} <br />
</Text> Tindakan ini tidak dapat diubah.
? Tindakan ini tidak dapat diubah. </AlertDialogDescription>
</Text> </AlertDialogHeader>
<AlertDialogFooter>
{/* {errorMessage && <Alert color="red">{errorMessage}</Alert>} */} <AlertDialogCancel
{/* Buttons */}
<Flex justify="flex-end" align="center" gap="lg" mt="lg">
<Button
variant="outline"
onClick={() => navigate({ search: {} })} onClick={() => navigate({ search: {} })}
disabled={mutation.isPending} disabled={mutation.isPending}
> >
Batal Batal
</Button> </AlertDialogCancel>
<Button <Button
variant="subtle" variant="default"
// leftSection={<TbDeviceFloppy size={20} />}
type="submit"
color="red" color="red"
loading={mutation.isPending}
onClick={() => mutation.mutate({ id: userId })} onClick={() => mutation.mutate({ id: userId })}
disabled={mutation.isPending}
> >
Hapus Pengguna {mutation.isPending ? "Hapus..." : "Hapus Pengguna"}
</Button> </Button>
</Flex> </AlertDialogFooter>
</Modal> </AlertDialogContent>
</AlertDialog>
); );
} }

View File

@ -1,19 +1,16 @@
import client from "../../../honoClient";
import stringToColorHex from "@/utils/stringToColorHex"; import stringToColorHex from "@/utils/stringToColorHex";
import { import {
Avatar, Avatar,
Button, AvatarFallback,
Center, AvatarImage
Flex, } from "@/shadcn/components/ui/avatar";
Modal, import { Modal, ScrollArea } from "@mantine/core";
ScrollArea, import { Button } from "@/shadcn/components/ui/button";
Stack,
} from "@mantine/core";
import { useForm } from "@mantine/form"; import { useForm } from "@mantine/form";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { getRouteApi } from "@tanstack/react-router"; import { getRouteApi } from "@tanstack/react-router";
import { createUser, updateUser } from "../queries/userQueries"; import { createUser, updateUser } from "../queries/userQueries";
import { TbDeviceFloppy } from "react-icons/tb";
import client from "../../../honoClient";
import { getUserByIdQueryOptions } from "../queries/userQueries"; import { getUserByIdQueryOptions } from "../queries/userQueries";
import { useEffect } from "react"; import { useEffect } from "react";
import { notifications } from "@mantine/notifications"; import { notifications } from "@mantine/notifications";
@ -199,19 +196,18 @@ export default function UserFormModal() {
size="md" size="md"
> >
<form onSubmit={form.onSubmit((values) => handleSubmit(values))}> <form onSubmit={form.onSubmit((values) => handleSubmit(values))}>
<Stack mt="sm" gap="lg" px="lg"> <div className="flex items-center justify-center my-2">
{/* Avatar */} <div className="h-120 w-120 rounded-full overflow-hidden">
<Center> <Avatar className="h-[120px] w-[120px] rounded-full overflow-hidden">
<Avatar <AvatarImage src={form.values.photoProfileUrl} alt={form.values.name} />
color={stringToColorHex(form.values.id ?? "")} <AvatarFallback style={{ backgroundColor: stringToColorHex(form.values.id ?? ""), fontSize: "60px", color: "white", fontWeight: "bold" }}>
src={form.values.photoProfileUrl} {form.values.name?.[0]?.toUpperCase() ?? "?"}
size={120} </AvatarFallback>
>
{form.values.name?.[0]?.toUpperCase()}
</Avatar> </Avatar>
</Center> </div>
</Stack> </div>
<ScrollArea className="h-72 pr-4">
{createInputComponents({ {createInputComponents({
disableAll: mutation.isPending, disableAll: mutation.isPending,
readonlyAll: formType === "detail", readonlyAll: formType === "detail",
@ -277,9 +273,10 @@ export default function UserFormModal() {
}, },
], ],
})} })}
</ScrollArea>
{/* Buttons */} {/* Buttons */}
<Flex justify="flex-end" align="center" gap="lg" mt="lg"> <div className="flex justify-end align-center gap-1 mt-4">
<Button <Button
variant="outline" variant="outline"
onClick={() => navigate({ search: {} })} onClick={() => navigate({ search: {} })}
@ -289,15 +286,14 @@ export default function UserFormModal() {
</Button> </Button>
{formType !== "detail" && ( {formType !== "detail" && (
<Button <Button
variant="filled" variant="default"
leftSection={<TbDeviceFloppy size={20} />}
type="submit" type="submit"
loading={mutation.isPending} disabled={mutation.isPending}
> >
Simpan Simpan
</Button> </Button>
)} )}
</Flex> </div>
</form> </form>
</Modal> </Modal>
); );

View File

@ -4,7 +4,6 @@ import { createLazyFileRoute } from "@tanstack/react-router";
import UserFormModal from "@/modules/usersManagement/modals/UserFormModal"; import UserFormModal from "@/modules/usersManagement/modals/UserFormModal";
import ExtractQueryDataType from "@/types/ExtractQueryDataType"; import ExtractQueryDataType from "@/types/ExtractQueryDataType";
import { createColumnHelper } from "@tanstack/react-table"; import { createColumnHelper } from "@tanstack/react-table";
import { Badge, Flex } from "@mantine/core";
import createActionButtons from "@/utils/createActionButton"; import createActionButtons from "@/utils/createActionButton";
import { TbEye, TbPencil, TbTrash } from "react-icons/tb"; import { TbEye, TbPencil, TbTrash } from "react-icons/tb";
import UserDeleteModal from "@/modules/usersManagement/modals/UserDeleteModal"; import UserDeleteModal from "@/modules/usersManagement/modals/UserDeleteModal";
@ -61,7 +60,7 @@ export default function UsersPage() {
columnHelper.display({ columnHelper.display({
header: "Aksi", header: "Aksi",
cell: (props) => ( cell: (props) => (
<Flex gap="xs"> <div className="flex gap-x-2">
{createActionButtons([ {createActionButtons([
{ {
label: "Detail", label: "Detail",
@ -85,7 +84,7 @@ export default function UsersPage() {
icon: <TbTrash />, icon: <TbTrash />,
}, },
])} ])}
</Flex> </div>
), ),
}), }),
]} ]}