diff --git a/.gitignore b/.gitignore index 3c188ab..cfd623b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ dist tmp /out-tsc +apps/iot/build # dependencies node_modules diff --git a/apps/app/src/components/operator-tabs.tsx b/apps/app/src/components/operator-tabs.tsx index 39beb2e..626a637 100644 --- a/apps/app/src/components/operator-tabs.tsx +++ b/apps/app/src/components/operator-tabs.tsx @@ -4,10 +4,11 @@ import { IonRouterOutlet, IonTabs, IonTabBar, IonTabButton, IonLabel } from "@io import { Icons, OperatorContext } from "@trashtrack/ui"; import OperatorDashboard from "../pages/operator/dashboard"; -import OperatorUserDisplay from "../pages/operator/user/display"; import { useContext } from "react"; -import OperatorUserEdit from "../pages/operator/user/edit-user"; -import OperatorUserEditPassword from "../pages/operator/user/edit-password-user"; +import { UsersPage } from "../pages/operator/user/users.page"; +import { DetailedUserPage } from "../pages/operator/user/detailed-user.page"; +import { ChangeUserPage } from "../pages/operator/user/change-user.page"; +import { CreateUserPage } from "../pages/operator/user/create-user.page"; const OperatorTabs: React.FC = () => { const operator = useContext(OperatorContext); @@ -19,13 +20,11 @@ const OperatorTabs: React.FC = () => { } exact={true} /> - } exact={true} /> - } exact={true} /> - } - exact={true} - /> + } exact={true} /> + } exact={true} /> + } exact={true} /> + } exact={true} /> + } exact={true} /> @@ -37,12 +36,12 @@ const OperatorTabs: React.FC = () => { {t("tabs.trashbin")} - {/* {isAdmin && ( + {isAdmin && ( User - )} */} + )} ); diff --git a/apps/app/src/locales/en.json b/apps/app/src/locales/en.json index b22ab70..6b394c8 100644 --- a/apps/app/src/locales/en.json +++ b/apps/app/src/locales/en.json @@ -87,6 +87,80 @@ "login": "Back to Login", "home": "Back to Home" }, + "user": { + "subtitle": "User", + "search": "Search User", + "create": "Create a new user", + "noResults": "No user found for the search.", + "view_details": "View Details", + "not_active": "Not Active", + "is_active": "Active", + "detailed": { + "name": "Name", + "username": "Username", + "phoneNumber": "Phone Number", + "role": "Role", + "active": "Active", + "description": "Description", + "edit": "Change", + "change_password": "Change Password", + "delete": "Delete", + "back": "Back", + "action": "Actions", + "dialog_delete": { + "title": "Are you sure you want to delete this user?", + "subtitle": "This action cannot be undone.", + "pending": "Pending...", + "delete": "Delete", + "cancel": "Cancel" + } + }, + "create_user": { + "subtitle": "Create User", + "name": "Name", + "password": "Password", + "username": "Username", + "phoneNumber": "Phone Number", + "description": "Description", + "role": "Role", + "submit": "Create User", + "back": "Back", + "validation": { + "name": "Name must be at least 8 characters long.", + "username": "Username must be at least 8 characters long.", + "phoneNumber": "Phone number must be at least 8 characters long.", + "description": "Description must be at least 8 characters long." + } + }, + "change_user": { + "subtitle": "Change User", + "name": "Name", + "username": "Username", + "phoneNumber": "Phone Number", + "description": "Description", + "role": "Role", + "active": "Active", + "submit": "Update User", + "back": "Back", + "validation": { + "name": "Name must be at least 8 characters long.", + "username": "Username must be at least 8 characters long.", + "phoneNumber": "Phone number must be at least 8 characters long.", + "description": "Description must be at least 8 characters long." + } + }, + "change_password": { + "subtitle": "Change Password", + "oldPassword": "Old Password", + "newPassword": "New Password", + "submit": "Change Password", + "back": "Back", + "validation": { + "old_password": "Old password must be at least 8 characters long.", + "new_password": "New password must be at least 8 characters long." + } + } + }, "trashbin": { "subtitle": "Trash Bin", "create": "Create a new trash bin", diff --git a/apps/app/src/locales/id.json b/apps/app/src/locales/id.json index 0efa9b9..e085f7c 100644 --- a/apps/app/src/locales/id.json +++ b/apps/app/src/locales/id.json @@ -87,6 +87,81 @@ "login": "Kembali ke Login", "home": "Kembali ke Home" }, + "user": { + "subtitle": "Pengguna", + "search": "Cari Pengguna", + "create": "Buat Pengguna", + "noResults": "Tidak ada pengguna ditemukan.", + "view_details": "Lihat Detail", + "not_active": "Tidak Aktif", + "is_active": "Aktif", + "detailed": { + "name": "Nama", + "username": "Username", + "phoneNumber": "Nomor Telepon", + "role": "Role", + "active": "Status Aktif", + "description": "Deskripsi", + "edit": "Ubah", + "change_password": "Ubah Kata Sandi", + "delete": "Hapus", + "back": "Kembali", + "action": "Aksi", + "dialog_delete": { + "title": "Apakah Anda yakin ingin menghapus pengguna ini?", + "subtitle": "Tindakan ini tidak dapat dibatalkan.", + "pending": "Memproses...", + "delete": "Hapus", + "cancel": "Batal" + } + }, + "create_user": { + "subtitle": "Buat Pengguna", + "name": "Name", + "password": "Kata Sandi", + "username": "Username", + "phoneNumber": "Nomor Telepon", + "description": "Deskripsi", + "role": "Role", + "submit": "Buat Pengguna", + "back": "Kembali", + "validation": { + "name": "Nama harus minimal 8 karakter.", + "username": "Username harus minimal 8 karakter.", + "password": "Kata sandi harus minimal 8 karakter.", + "phoneNumber": "Nomor telepon harus minimal 8 karakter.", + "description": "Deskripsi harus minimal 8 karakter." + } + }, + "change_user": { + "subtitle": "Ubah Pengguna", + "name": "Nama", + "username": "Nama Pengguna", + "phoneNumber": "Nomor Telepon", + "description": "Deskripsi", + "role": "Peran", + "active": "Aktif", + "submit": "Perbarui Pengguna", + "back": "Kembali", + "validation": { + "name": "Nama harus memiliki setidaknya 8 karakter.", + "username": "Nama pengguna harus memiliki setidaknya 8 karakter.", + "phoneNumber": "Nomor telepon harus memiliki setidaknya 8 karakter.", + "description": "Deskripsi harus memiliki setidaknya 8 karakter." + } + }, + "change_password": { + "subtitle": "Ubah Kata Sandi", + "oldPassword": "Kata Sandi Lama", + "newPassword": "Kata Sandi Baru", + "submit": "Ubah Kata Sandi", + "back": "Kembali", + "validation": { + "old_password": "Kata sandi lama harus memiliki setidaknya 8 karakter.", + "new_password": "Kata sandi baru harus memiliki setidaknya 8 karakter." + } + } + }, "trashbin": { "subtitle": "Tempat Sampah", "create": "Buat Tempat Sampah", diff --git a/apps/app/src/pages/operator/trash-bin/report/report-feedback/feedback.page.tsx b/apps/app/src/pages/operator/trash-bin/report/report-feedback/feedback.page.tsx index 8713994..2f5815f 100644 --- a/apps/app/src/pages/operator/trash-bin/report/report-feedback/feedback.page.tsx +++ b/apps/app/src/pages/operator/trash-bin/report/report-feedback/feedback.page.tsx @@ -143,28 +143,32 @@ export function FeedbackPage() { )} - {isLoading ? ( - - - - - - - - - +
+ {isLoading ? ( + + + + + + + + + + - - - ) : ( - - - {filteredData.length === 0 ? ( + + ) : filteredData.length === 0 ? ( + +

{t("operator.reports.feedback.delete.noResults")}

- ) : ( - filteredData.map((feedback: InterfaceFeedback) => ( +
+
+ ) : ( + filteredData.map((feedback: InterfaceFeedback) => ( + +

{feedback.title}

{feedback.description}

@@ -188,11 +192,11 @@ export function FeedbackPage() { queryClient={queryClient} />
- )) - )} -
-
- )} + + + )) + )} +
diff --git a/apps/app/src/pages/operator/user/change-user.page.tsx b/apps/app/src/pages/operator/user/change-user.page.tsx new file mode 100644 index 0000000..9fd7075 --- /dev/null +++ b/apps/app/src/pages/operator/user/change-user.page.tsx @@ -0,0 +1,7 @@ +export function ChangeUserPage() { + return ( +
+
+
+ ); +} diff --git a/apps/app/src/pages/operator/user/create-user.page.tsx b/apps/app/src/pages/operator/user/create-user.page.tsx new file mode 100644 index 0000000..3f7fae0 --- /dev/null +++ b/apps/app/src/pages/operator/user/create-user.page.tsx @@ -0,0 +1,7 @@ +export function CreateUserPage() { + return ( +
+
+
+ ); +} diff --git a/apps/app/src/pages/operator/user/detailed-user.page.tsx b/apps/app/src/pages/operator/user/detailed-user.page.tsx new file mode 100644 index 0000000..caeb673 --- /dev/null +++ b/apps/app/src/pages/operator/user/detailed-user.page.tsx @@ -0,0 +1,7 @@ +export function DetailedUserPage() { + return ( +
+
+
+ ); +} diff --git a/apps/app/src/pages/operator/user/display.tsx b/apps/app/src/pages/operator/user/display.tsx deleted file mode 100644 index 61081be..0000000 --- a/apps/app/src/pages/operator/user/display.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { IonContent, IonPage } from "@ionic/react"; -import { Button, Card, CardContent, CardHeader, Icons } from "@trashtrack/ui"; -import { useGetUsersQuery } from "../../../queries/get-users-query"; -import { IonFab, IonFabButton } from "@ionic/react"; -import { useState } from "react"; -import { UserCreationSheet, UserDeleteConfirmationDialog, UserDetailsSheet } from "@trashtrack/ui"; -import { useHistory } from "react-router-dom"; - -export function OperatorUserDisplay() { - const history = useHistory(); - - const { data, isLoading, refetch } = useGetUsersQuery(); - const [isUserCreationSheetOpen, setIsUserCreationSheetOpen] = useState(false); - const [isUserDeleteConfirmationOpen, setIsUserDeleteConfirmationOpen] = useState(false); - const [isUserDetailsSheetOpen, setIsUserDetailsSheetOpen] = useState(false); - - return ( - - -
-

TrashTrack

-

User Management

-
-
- {isLoading ? ( - - -

Loading...

-
-
- ) : ( - data.data?.map((user: { id: number; username: string; role: string; active: boolean }) => ( - - -
setIsUserDetailsSheetOpen(true)}> -

Username: {user.username}

-

- Level: {user.role}
- Status: {user.active ? "Active" : "Inactive"} -

-
-
- - - - - - - - -
- )) - )} -
- - -
- - setIsUserCreationSheetOpen(true)}> - - - -
- ); -} - -export default OperatorUserDisplay; diff --git a/apps/app/src/pages/operator/user/edit-password-user.tsx b/apps/app/src/pages/operator/user/edit-password-user.tsx deleted file mode 100644 index c8cfd8e..0000000 --- a/apps/app/src/pages/operator/user/edit-password-user.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { IonContent, IonPage } from "@ionic/react"; -import { useParams } from "react-router-dom"; - -export function OperatorUserEditPassword() { - const { id } = useParams<{ id: string }>(); - - return ( - - -
-

TrashTrack

-

Edit User Password

-
-
-
-
- ); -} - -export default OperatorUserEditPassword; diff --git a/apps/app/src/pages/operator/user/edit-user.tsx b/apps/app/src/pages/operator/user/edit-user.tsx deleted file mode 100644 index fc4bfb5..0000000 --- a/apps/app/src/pages/operator/user/edit-user.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { IonContent, IonPage } from "@ionic/react"; -import { useParams } from "react-router-dom"; -import { useGetUserQuery, IUserQuery } from "../../../queries/get-user-query"; -import { UserEditForm } from "@trashtrack/ui"; -import { useGetUsersQuery } from "../../../queries/get-users-query"; - -export function OperatorUserEdit() { - const { user_id } = useParams<{ user_id: string }>(); - const { refetch } = useGetUsersQuery(); - - const { data, isLoading, isError } = useGetUserQuery(user_id); - - return ( - - -
-

TrashTrack

-

Edit User

-
-
- {isError &&

Error fetching user

} - {isLoading ? ( -

Loading...

- ) : ( - - )} -
-
-
- ); -} - -export default OperatorUserEdit; diff --git a/apps/app/src/pages/operator/user/users.page.tsx b/apps/app/src/pages/operator/user/users.page.tsx new file mode 100644 index 0000000..16a5cee --- /dev/null +++ b/apps/app/src/pages/operator/user/users.page.tsx @@ -0,0 +1,7 @@ +export function UsersPage() { + return ( +
+
+
+ ); +} diff --git a/apps/iot/iot.ino b/apps/iot/iot.ino new file mode 100644 index 0000000..e69de29 diff --git a/libs/components/src/forms/operator/user/change-user.form.tsx b/libs/components/src/forms/operator/user/change-user.form.tsx new file mode 100644 index 0000000..e1a68a4 --- /dev/null +++ b/libs/components/src/forms/operator/user/change-user.form.tsx @@ -0,0 +1,7 @@ +export function ChangeUserForm({ userId }: { userId: string }) { + return ( +
+
+
+ ); +} diff --git a/libs/components/src/forms/operator/user/create-user.form.tsx b/libs/components/src/forms/operator/user/create-user.form.tsx new file mode 100644 index 0000000..97c8bb0 --- /dev/null +++ b/libs/components/src/forms/operator/user/create-user.form.tsx @@ -0,0 +1,7 @@ +export function CreateUserForm() { + return ( +
+
+
+ ); +} diff --git a/libs/components/src/forms/operator/user/user-edit.tsx b/libs/components/src/forms/operator/user/user-edit.tsx deleted file mode 100644 index 61e7e2e..0000000 --- a/libs/components/src/forms/operator/user/user-edit.tsx +++ /dev/null @@ -1,456 +0,0 @@ -import { z } from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { useMutation } from "@tanstack/react-query"; -import { API_URL } from "@trashtrack/utils"; -import { Button, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Checkbox } from "../../../index"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../../ui/form"; -import { useMemo, useState } from "react"; -import { - AlertDialog, - AlertDialogCancel, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogContent, -} from "../../../ui/alert-dialog"; -import { useHistory } from "react-router-dom"; - -enum Role { - operator = "operator", - admin = "admin", -} - -interface User { - id: number; - name: string; - username: string; - password: string; - phoneNumber: string; - role: Role; - active: boolean; - description: string; -} - -const formSchema = z.object({ - name: z.string().optional().nullable(), - username: z.coerce.string().optional().nullable(), - password: z.string().optional(), - phoneNumber: z.string().optional().nullable(), - role: z - .nativeEnum(Role) - .refine((value) => value !== null, { - message: "Role is required.", - }) - .optional() - .nullable(), - active: z - .boolean() - .refine((value) => value !== null, { - message: "Active is required.", - }) - .optional() - .nullable(), - description: z.string().nullable().optional(), -}); - -const formPasswordSchema = z.object({ - oldPassword: z.string().min(8, { - message: "Password harus terdiri dari minimal 8 karakter.", - }), - newPassword: z.string().min(8, { - message: "Password harus terdiri dari minimal 8 karakter.", - }), - confirmPassword: z.string().min(8, { - message: "Password harus terdiri dari minimal 8 karakter.", - }), -}); - -export function UserUpdatePasswordDialog({ - id, - refetchUser, - isOpen, - setIsOpen, -}: { - id: string; - refetchUser: () => void; - isOpen: boolean; - setIsOpen: (value: boolean) => void; -}) { - const history = useHistory(); - - const form = useForm>({ - resolver: zodResolver(formPasswordSchema), - defaultValues: { - oldPassword: "", - newPassword: "", - confirmPassword: "", - }, - }); - - const { - mutateAsync, - isPending, - isError, - isSuccess, - reset: resetMutation, - } = useMutation({ - mutationKey: ["updateUser"], - mutationFn: (formData: { id: string; oldPassword: string; newPassword: string; confirmPassword: string }) => { - return fetch(API_URL + `/user/${id}/password`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - body: JSON.stringify(formData), - }).then((res) => res.json()); - }, - onSuccess: (dataMutation) => { - form.reset(); - resetMutation(); - history.replace("/operator/tabs/user"); - }, - }); - - async function onSubmit(values: z.infer) { - await mutateAsync({ - id: id, - oldPassword: values.oldPassword, - newPassword: values.newPassword, - confirmPassword: values.confirmPassword, - }); - } - - return ( - - - Update password -
-
- - ( - - Old Password - - field.onChange(e.target.value)} - /> - - - - )} - /> - ( - - New Password - - field.onChange(e.target.value)} - /> - - - - )} - /> - ( - - Confirm Password - - field.onChange(e.target.value)} - /> - - - - )} - /> -
- - {isSuccess && ( -
- Password updated successfully. -
- )} - {isError && ( -
- There was an error updating the password. Please try again. -
- )} -
- - -
- - - Cancel - -
-
- ); -} - -export function UserEditForm({ id, refetch, user }: { id: string; refetch: () => void; user: User }) { - const [isUpdatePasswordDialogOpen, setIsUpdatePasswordDialogOpen] = useState(false); - const history = useHistory(); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: useMemo(() => { - return { - name: "", - username: "", - password: "", - phoneNumber: "", - role: Role.operator, - active: false, - description: "", - }; - }, []), - }); - - // useEffect(() => { - // form.reset(user); - // }, [form, user]); - - const { - mutateAsync, - isPending, - isError, - isSuccess, - reset: resetMutation, - } = useMutation({ - mutationKey: ["updateUser"], - mutationFn: (formData: { - name?: string; - username?: string; - password?: string; - phoneNumber?: string; - role?: Role; - active?: boolean; - description?: string; - }) => { - return fetch(API_URL + `/user/${user.id}`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - body: JSON.stringify(formData), - }).then((res) => res.json()); - }, - onSuccess: (dataMutation) => { - form.reset(); - resetMutation(); - refetch(); - history.replace("/operator/tabs/user"); - }, - }); - - async function onSubmit(values: z.infer) { - const formData = { - name: values.name || undefined, - username: values.username ? values.username.toLowerCase() : undefined, - password: values.password || undefined, - phoneNumber: values.phoneNumber || undefined, - role: values.role || undefined, - active: values.active || undefined, - description: values.description || undefined, - }; - - await mutateAsync(formData); - } - - return ( -
- - ( - - Name - - field.onChange(e.target.value)} - /> - - - - )} - /> - ( - - Username - - field.onChange(e.target.value)} - /> - - - - )} - /> - ( - - )} - /> - ( - - Phone Number - - field.onChange(e.target.value)} - /> - - - - )} - /> - - ( - - Role - - - - )} - /> - - ( - - Active? - - - - - - )} - /> - - ( - - Description - - field.onChange(e.target.value)} - // onChange={(e) => field.onChange(e.target.value)} - /> - - - - )} - /> - -
- - - {isSuccess &&
User created successfully.
} - {isError && ( -
- There was an error creating the user. Please try again. -
- )} - -
- - - - - ); -} diff --git a/libs/components/src/forms/sheets/user-creation.tsx b/libs/components/src/forms/sheets/user-creation.tsx deleted file mode 100644 index 49d22ba..0000000 --- a/libs/components/src/forms/sheets/user-creation.tsx +++ /dev/null @@ -1,279 +0,0 @@ -import { - Button, - Input, - Sheet, - SheetClose, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetTitle, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Checkbox, -} from "../../index"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../ui/form"; - -import { z } from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { useMutation } from "@tanstack/react-query"; -import { API_URL } from "@trashtrack/utils"; - -enum Role { - operator = "operator", - admin = "admin", -} - -const formSchema = z.object({ - name: z.string().min(4, { - message: "Nama harus terdiri dari minimal 4 karakter.", - }), - username: z.coerce.string().min(4, { - message: "Username harus terdiri dari minimal 8 karakter.", - }), - password: z.string().min(4, { - message: "Password harus terdiri dari minimal 4 karakter.", - }), - phoneNumber: z.string().min(4, { - message: "Nomor telepon harus terdiri dari minimal 4 karakter.", - }), - role: z.nativeEnum(Role).refine((value) => value !== null, { - message: "Role is required.", - }), - active: z.boolean().refine((value) => value !== null, { - message: "Active is required.", - }), - description: z.string().optional(), -}); - -export function UserCreationSheet({ - refetchUser, - isOpen, - setIsOpen, -}: { - refetchUser: () => void; - isOpen: boolean; - setIsOpen: (value: boolean) => void; -}) { - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - name: "", - active: true, - username: "", - password: "", - phoneNumber: "", - role: Role.operator, - description: "", - }, - }); - - const { - mutateAsync, - isPending, - isError, - isSuccess, - reset: resetMutation, - } = useMutation({ - mutationKey: ["createUser"], - mutationFn: (formData: { - name?: string; - username?: string; - password?: string; - phoneNumber?: string; - role?: Role; - active?: boolean; - description?: string; - }) => { - return fetch(API_URL + `/user`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - body: JSON.stringify(formData), - }).then((res) => res.json()); - }, - onSuccess: (dataMutation) => { - form.reset(); - resetMutation(); - - refetchUser(); - setIsOpen(false); - }, - }); - - async function onSubmit(values: z.infer) { - await mutateAsync({ - name: values.name, - username: values.username.toLowerCase(), - password: values.password, - phoneNumber: values.phoneNumber, - role: values.role, - active: values.active, - description: values.description, - }); - } - - return ( - - - - Create a new user - Fill in the details to create a new user. - -
- - ( - - Name - - - - - - )} - /> - ( - - Username - - - - - - )} - /> - ( - - Password - - - - - - )} - /> - ( - - Phone Number - - - - - - )} - /> - - ( - - Role - - - - )} - /> - - ( - - Active? - - - - - - )} - /> - - ( - - Description - - - - - - )} - /> - -
- - {isSuccess && ( -
User created successfully.
- )} - {isError && ( -
- There was an error creating the user. Please try again. -
- )} -
- - - - - - - - -
-
- ); -} diff --git a/libs/components/src/forms/sheets/user-details.tsx b/libs/components/src/forms/sheets/user-details.tsx deleted file mode 100644 index 2547834..0000000 --- a/libs/components/src/forms/sheets/user-details.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { - Input, - Label, - Sheet, - SheetContent, - SheetHeader, - SheetTitle, - SheetFooter, - SheetClose, - Button, -} from "../../index"; -import { API_URL } from "@trashtrack/utils"; - -export function UserDetailsSheet({ - id, - isOpen, - setIsOpen, -}: { - id: string; - isOpen: boolean; - setIsOpen: (value: boolean) => void; -}) { - const { data, isLoading } = useQuery({ - queryKey: ["getUser"], - queryFn: () => fetch(API_URL + `/user/id/${id}`).then((res) => res.json()), - }); - - return ( - - - {isLoading ? ( -
Loading...
- ) : ( -
- - User Details - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - - - - -
- )} -
-
- ); -} diff --git a/libs/components/src/forms/sheets/user-edit.tsx b/libs/components/src/forms/sheets/user-edit.tsx deleted file mode 100644 index 81c9f44..0000000 --- a/libs/components/src/forms/sheets/user-edit.tsx +++ /dev/null @@ -1,352 +0,0 @@ -/* eslint-disable react-hooks/rules-of-hooks */ -import { - Button, - Input, - Sheet, - SheetClose, - SheetContent, - SheetDescription, - SheetFooter, - SheetHeader, - SheetTitle, - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, - Checkbox, -} from "../../index"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../../ui/form"; -import { - AlertDialog, - AlertDialogCancel, - AlertDialogFooter, - AlertDialogHeader, - AlertDialogContent, -} from "../../ui/alert-dialog"; - -import { z } from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { useMutation, useQuery } from "@tanstack/react-query"; -import { API_URL } from "@trashtrack/utils"; -import { useState } from "react"; - -enum Role { - operator = "operator", - admin = "admin", -} - -const formSchema = z.object({ - name: z.string().min(4, { - message: "Nama harus terdiri dari minimal 4 karakter.", - }), - username: z.coerce.string().min(4, { - message: "Username harus terdiri dari minimal 8 karakter.", - }), - password: z.string().min(4, { - message: "Password harus terdiri dari minimal 4 karakter.", - }), - phoneNumber: z.string().min(4, { - message: "Nomor telepon harus terdiri dari minimal 4 karakter.", - }), - role: z.nativeEnum(Role).refine((value) => value !== null, { - message: "Role is required.", - }), - active: z.boolean().refine((value) => value !== null, { - message: "Active is required.", - }), - description: z.string().nullable().optional(), -}); - -export function UserUpdatePasswordDialog({ - id, - refetchUser, - isOpen, - setIsOpen, -}: { - id: string; - refetchUser: () => void; - isOpen: boolean; - setIsOpen: (value: boolean) => void; -}) { - return ( - - - Update password - - - - - Cancel - - - - ); -} - -export function UserEditSheet({ - id, - refetchUser, - isOpen, - setIsOpen, -}: { - id: string; - refetchUser: () => void; - isOpen: boolean; - setIsOpen: (value: boolean) => void; -}) { - const [isUpdatePasswordDialogOpen, setIsUpdatePasswordDialogOpen] = useState(false); - - const { - data, - isLoading, - refetch: refetchThisUser, - } = useQuery({ - queryKey: ["getUser"], - queryFn: () => fetch(API_URL + `/user/id/${id}`).then((res) => res.json()), - }); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - name: isLoading ? "" : data.data.name, - active: isLoading ? false : data.data.active, - username: isLoading ? "" : data.data.username, - password: isLoading ? "" : data.data.password, - phoneNumber: isLoading ? "" : data.data.phoneNumber, - role: isLoading ? Role.operator : data.data.role, - description: isLoading ? "" : data.data.description, - }, - }); - - const { - mutateAsync, - isPending, - isError, - isSuccess, - reset: resetMutation, - } = useMutation({ - mutationKey: ["updateUser"], - mutationFn: (formData: { - name?: string; - username?: string; - password?: string; - phoneNumber?: string; - role?: Role; - active?: boolean; - description?: string; - }) => { - return fetch(API_URL + `/user/${id}`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - body: JSON.stringify(formData), - }).then((res) => res.json()); - }, - onSuccess: (dataMutation) => { - form.reset(); - resetMutation(); - - refetchUser(); - setIsOpen(false); - }, - }); - - async function onSubmit(values: z.infer) { - await mutateAsync({ - name: values.name, - username: values.username.toLowerCase(), - password: values.password, - phoneNumber: values.phoneNumber, - role: values.role, - active: values.active, - description: values.description || undefined, - }); - } - - return ( - - - - Create a new user - Fill in the details to create a new user. - -
- - ( - - Name - - field.onChange(e.target.value)} - /> - - - - )} - /> - ( - - Username - - - - - - )} - /> - ( - - )} - /> - ( - - Phone Number - - - - - - )} - /> - - ( - - Role - - - - )} - /> - - ( - - Active? - - - - - - )} - /> - - ( - - Description - - field.onChange(e.target.value)} - // {...field} - /> - - - - )} - /> - -
- - - {isSuccess && ( -
User created successfully.
- )} - {isError && ( -
- There was an error creating the user. Please try again. -
- )} -
- - - - - - - - - - -
-
- ); -} diff --git a/libs/components/src/index.ts b/libs/components/src/index.ts index 3a497a2..da8d5a9 100644 --- a/libs/components/src/index.ts +++ b/libs/components/src/index.ts @@ -23,10 +23,9 @@ export * from "./api/operator-context"; export * from "./forms/operator/auth/login-form"; export * from "./forms/complain/laporan/laporan-form"; -export * from "./forms/operator/user/user-edit"; +export * from "./forms/operator/user/create-user.form"; +export * from "./forms/operator/user/change-user.form"; -export * from "./forms/sheets/user-creation"; -export * from "./forms/sheets/user-details"; export * from "./forms/sheets/delete-confirmation"; export * from "./forms/operator/trash-bin/create-feedback.form";