diff --git a/app/(admin)/admin/article/page.tsx b/app/(admin)/admin/article/page.tsx index 6ffff9f..c8c8fbd 100644 --- a/app/(admin)/admin/article/page.tsx +++ b/app/(admin)/admin/article/page.tsx @@ -7,19 +7,6 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; export default function BasicPage() { - const router = useRouter(); - const setGeneratedArticleIdStore = generatedArticleIds( - (state) => state.setArticleIds - ); - const goGenerate = () => { - setGeneratedArticleIdStore({ - singleArticle: [], - bulkArticle: [], - rewriteArticle: [], - }); - router.push("/admin/article/generate"); - }; - return (
diff --git a/app/(admin)/settings/page.tsx b/app/(admin)/settings/page.tsx index 1223af6..6b3e751 100644 --- a/app/(admin)/settings/page.tsx +++ b/app/(admin)/settings/page.tsx @@ -1,15 +1,25 @@ "use client"; import PasswordForm from "@/components/form/settings/password"; import ProfileForm from "@/components/form/settings/profile"; +import { getProfile } from "@/service/master-user"; import { Tab, Tabs } from "@nextui-org/react"; +import { useEffect, useState } from "react"; export default function Settings() { + const [profile, setProfile] = useState(); + useEffect(() => { + const initFetch = async () => { + const profile = await getProfile(); + setProfile(profile?.data?.data); + }; + initFetch(); + }, []); return (
- + diff --git a/app/auth/layout.tsx b/app/auth/layout.tsx index feb3fd4..c9e99f9 100644 --- a/app/auth/layout.tsx +++ b/app/auth/layout.tsx @@ -1,5 +1,3 @@ -import { HumasLayout } from "@/components/layout/humas-layout"; - export default function AuthLayout({ children, }: { diff --git a/app/setup-password/layout.tsx b/app/setup-password/layout.tsx new file mode 100644 index 0000000..c9e99f9 --- /dev/null +++ b/app/setup-password/layout.tsx @@ -0,0 +1,7 @@ +export default function AuthLayout({ + children, +}: { + children: React.ReactNode; +}) { + return <> {children}; +} diff --git a/app/setup-password/page.tsx b/app/setup-password/page.tsx new file mode 100644 index 0000000..eb07c37 --- /dev/null +++ b/app/setup-password/page.tsx @@ -0,0 +1,191 @@ +"use client"; +import { Input } from "@nextui-org/input"; +import React, { useState } from "react"; +import { Button } from "@nextui-org/button"; +import Link from "next/link"; +import Cookies from "js-cookie"; +import { close, error, loading } from "@/config/swal"; +import { getProfile, postSignIn } from "@/service/master-user"; +import { useRouter, useSearchParams } from "next/navigation"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { EyeFilledIcon, EyeSlashFilledIcon } from "@/components/icons"; +import PasswordChecklist from "react-password-checklist"; + +export default function Login() { + const router = useRouter(); + const [isVisible, setIsVisible] = useState([false, false]); + const searchParams = useSearchParams(); + const userId = searchParams.get("id"); + + const [passwordConf, setPasswordConf] = useState(""); + const [password, setPassword] = useState(""); + const [isValidPassword, setIsValidPassword] = useState(false); + + const onSubmit = async () => { + const data = { + userId: String(userId), + password: password, + }; + + console.log("data", data); + }; + + const MySwal = withReactContent(Swal); + + const generatePassword = () => { + const length = Math.floor(Math.random() * 9) + 8; + + const upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const lowerCaseChars = "abcdefghijklmnopqrstuvwxyz"; + const numberChars = "0123456789"; + const specialChars = "!@#$%^&*"; + const allChars = + upperCaseChars + lowerCaseChars + numberChars + specialChars; + + let generatedPassword = ""; + + generatedPassword += + upperCaseChars[Math.floor(Math.random() * upperCaseChars.length)]; + generatedPassword += + specialChars[Math.floor(Math.random() * specialChars.length)]; + generatedPassword += + numberChars[Math.floor(Math.random() * numberChars.length)]; + generatedPassword += + lowerCaseChars[Math.floor(Math.random() * lowerCaseChars.length)]; + + for (let i = generatedPassword.length; i < length; i++) { + generatedPassword += + allChars[Math.floor(Math.random() * allChars.length)]; + } + + generatedPassword = generatedPassword + .split("") + .sort(() => 0.5 - Math.random()) + .join(""); + + setPassword(generatedPassword); + }; + + return ( +
+
+ + + +
+ +
+

+ Buat Password Baru +

+

Password

+ setIsVisible([!isVisible[0], isVisible[1]])} + > + {isVisible[0] ? ( + + ) : ( + + )} + + } + value={password} + onChange={(e: any) => { + setPassword(e.target.value.trim()); + }} + onPaste={(e: any) => { + setPassword(e.target.value.trim()); + }} + onCopy={(e: any) => { + setPassword(e.target.value.trim()); + }} + /> +

Konfirmasi Password

+ setIsVisible([isVisible[0], !isVisible[1]])} + > + {isVisible[1] ? ( + + ) : ( + + )} + + } + type={isVisible[1] ? "text" : "password"} + label="" + placeholder="" + value={passwordConf} + onChange={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} + onPaste={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} + onCopy={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} + /> + + Generate Password + + { + setIsValidPassword(isValid); + }} + className="text-white text-sm my-3" + messages={{ + minLength: "Password must be more than 8 characters", + specialChar: "Password must include a special character", + number: "Password must include a number", + capital: "Password must include an uppercase letter", + match: "Passwords match", + }} + /> + +
+ + Login + + {/*
+ Remember me +
*/} +
+
+
+ ); +} diff --git a/components/form/article/create-article-form.tsx b/components/form/article/create-article-form.tsx index 2aa72f1..1b915b1 100644 --- a/components/form/article/create-article-form.tsx +++ b/components/form/article/create-article-form.tsx @@ -94,7 +94,10 @@ export default function CreateArticleForm() { const [listCategory, setListCategory] = useState([]); const [tag, setTag] = useState(""); const [thumbnailImg, setThumbnailImg] = useState([]); - const [selectedMainImage, setSelectedMainImage] = useState(); + const [selectedMainImage, setSelectedMainImage] = useState( + null + ); + const [thumbnailValidation, setThumbnailValidation] = useState(""); const [diseData, setDiseData] = useState(); const { getRootProps, getInputProps } = useDropzone({ @@ -148,19 +151,24 @@ export default function CreateArticleForm() { }; const onSubmit = async (values: z.infer) => { - MySwal.fire({ - title: "Simpan Data", - text: "", - icon: "warning", - showCancelButton: true, - cancelButtonColor: "#d33", - confirmButtonColor: "#3085d6", - confirmButtonText: "Simpan", - }).then((result) => { - if (result.isConfirmed) { - save(values); - } - }); + if (thumbnailImg.length < 1 && !selectedMainImage) { + setThumbnailValidation("Required"); + } else { + setThumbnailValidation(""); + MySwal.fire({ + title: "Simpan Data", + text: "", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(values); + } + }); + } }; useEffect(() => { @@ -265,11 +273,8 @@ export default function CreateArticleForm() { const formFiles = new FormData(); if (selectedMainImage) { - formFiles.append("files", files[selectedMainImage]); + formFiles.append("files", files[selectedMainImage - 1]); - const resFile = await uploadArticleThumbnail(articleId, formFiles); - } else { - formFiles.append("files", files[0]); const resFile = await uploadArticleThumbnail(articleId, formFiles); } } @@ -348,8 +353,8 @@ export default function CreateArticleForm() { id={String(index)} value={String(index)} size="sm" - isSelected={selectedMainImage === index} - onValueChange={() => setSelectedMainImage(index)} + isSelected={selectedMainImage === index + 1} + onValueChange={() => setSelectedMainImage(index + 1)} >

Jadikan Thumbnail

@@ -395,6 +400,14 @@ export default function CreateArticleForm() { setValue("tags", uniqueArray as [string, ...string[]]); }; + useEffect(() => { + console.log("seklec", selectedMainImage); + console.log("seklssssec", files); + if (selectedMainImage) { + console.log("filll", files[selectedMainImage]); + } + }, [selectedMainImage]); + return (

Thubmnail

- {thumbnailImg.length > 0 ? ( + {selectedMainImage && files.length >= selectedMainImage ? ( +
+ thumbnail + +
+ ) : thumbnailImg.length > 0 ? (
) : ( <> - {" "} + {/* {" "} */} + {thumbnailValidation !== "" && ( +

Thumbnail harus ada

+ )} )} diff --git a/components/form/article/edit-article-form.tsx b/components/form/article/edit-article-form.tsx index 7bbbca3..7a9170f 100644 --- a/components/form/article/edit-article-form.tsx +++ b/components/form/article/edit-article-form.tsx @@ -20,6 +20,7 @@ import { getArticleById, updateArticle, uploadArticleFile, + uploadArticleThumbnail, } from "@/service/article"; import ReactSelect from "react-select"; import makeAnimated from "react-select/animated"; @@ -106,6 +107,11 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const [mainImage, setMainImage] = useState(0); const [thumbnail, setThumbnail] = useState(""); const [diseId, setDiseId] = useState(0); + const [thumbnailImg, setThumbnailImg] = useState([]); + const [selectedMainImage, setSelectedMainImage] = useState( + null + ); + const [thumbnailValidation, setThumbnailValidation] = useState(""); const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { @@ -141,10 +147,8 @@ export default function EditArticleForm(props: { isDetail: boolean }) { async function initState() { loading(); const res = await getArticleById(id); - // setArticle(data); const data = res.data?.data; setValue("title", data?.title); - // setTypeId(String(data?.typeId)); setValue("slug", data?.slug); setValue("description", data?.htmlDescription); setValue("tags", data?.tags ? data.tags.split(",") : []); @@ -161,8 +165,9 @@ export default function EditArticleForm(props: { isDetail: boolean }) { const temp: CategoryType[] = []; for (let i = 0; i < data.length; i++) { const datas = listCategory.filter((a) => a.id == data[i].id); - - temp.push(datas[0]); + if (datas[0]) { + temp.push(datas[0]); // Hanya tambahkan jika datas[0] ada + } } setValue("category", temp as [CategoryType, ...CategoryType[]]); }; @@ -234,6 +239,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { } } + if (thumbnailImg?.length > 0) { + const formFiles = new FormData(); + + formFiles.append("files", thumbnailImg[0]); + const resFile = await uploadArticleThumbnail(String(id), formFiles); + } + close(); successSubmit("/admin/article"); }; @@ -351,6 +363,13 @@ export default function EditArticleForm(props: { isDetail: boolean }) { }); }; + const handleFileChange = (event: React.ChangeEvent) => { + const selectedFiles = event.target.files; + if (selectedFiles) { + setThumbnailImg(Array.from(selectedFiles)); + } + }; + return ( handleDeleteFile(file?.id)} > @@ -563,7 +583,70 @@ export default function EditArticleForm(props: { isDetail: boolean }) {

Thubmnail

- thumbnail + {isDetail ? ( + thumbnail + ) : selectedMainImage && files.length >= selectedMainImage ? ( +
+ thumbnail + +
+ ) : thumbnail !== "" ? ( +
+ thumbnail + + +
+ ) : thumbnailImg.length > 0 ? ( +
+ thumbnail + +
+ ) : ( + <> + + {thumbnailValidation !== "" && ( +

Thumbnail harus ada

+ )} + + )}

Kategori

{ + MySwal.fire({ + title: "", + text: "", + html: ( + <> +

+ Kami telah mengirimkan tautan untuk mengatur ulang kata sandi ke + email Anda +

+

+ Apakah Anda sudah menerima emailnya? Jika belum, periksa folder spam + Anda +

+ + ), + icon: "info", + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Oke", + }).then((result) => { + if (result.isConfirmed) { + } + }); + }; + return ( -
+
-
-

Login

-

Username

- { - setValUsername(e.target.value.trim()); - }} - onPaste={(e: any) => { - setValUsername(e.target.value.trim()); - }} - onCopy={(e: any) => { - setValUsername(e.target.value.trim()); - }} - /> -

Password

- - {isVisible ? ( - - ) : ( - - )} - - } - type={isVisible ? "text" : "password"} - label="" - placeholder="" - onChange={(event) => setPassword(event.target.value)} - /> -
-
- Remember me -
- + {isResetPassword ? ( +
+

Reset Password - +

+

Username

+ { + setCheckUsernameValue(e.target.value.trim()); + }} + onPaste={(e: any) => { + setCheckUsernameValue(e.target.value.trim()); + }} + onCopy={(e: any) => { + setCheckUsernameValue(e.target.value.trim()); + }} + /> + + +
+ + Beranda + + {/*
+ Remember me +
*/} + setIsResetPassword(false)} + > + Login + +
- -
- Don't have accout yet?{" "} - - New Account - + ) : ( +
+

+ Login +

+

Username

+ { + setValUsername(e.target.value.trim()); + }} + onPaste={(e: any) => { + setValUsername(e.target.value.trim()); + }} + onCopy={(e: any) => { + setValUsername(e.target.value.trim()); + }} + /> +

Password

+ + {isVisible ? ( + + ) : ( + + )} + + } + type={isVisible ? "text" : "password"} + label="" + placeholder="" + onChange={(event) => setPassword(event.target.value)} + /> + + +
+ + Beranda + + {/*
+ Remember me +
*/} + setIsResetPassword(true)} + > + Reset Password + +
-
+ )}
); } diff --git a/components/form/magazine/create-magazine-form.tsx b/components/form/magazine/create-magazine-form.tsx index b28414b..7cc3b5c 100644 --- a/components/form/magazine/create-magazine-form.tsx +++ b/components/form/magazine/create-magazine-form.tsx @@ -33,7 +33,11 @@ import { PptIcon, WordIcon, } from "@/components/icons/globals"; -import { createMagazine, uploadMagazineFile } from "@/service/magazine"; +import { + createMagazine, + uploadMagazineFile, + uploadMagazineThumbnail, +} from "@/service/magazine"; const CustomEditor = dynamic( () => { @@ -85,6 +89,7 @@ export default function NewCreateMagazineForm() { const router = useRouter(); const editor = useRef(null); const [files, setFiles] = useState([]); + const [thumbnailImg, setThumbnailImg] = useState([]); const { getRootProps, getInputProps } = useDropzone({ onDrop: (acceptedFiles) => { @@ -105,8 +110,6 @@ export default function NewCreateMagazineForm() { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [ ".xlsx", ], - "application/vnd.ms-excel": [".xls"], - "text/csv": [".csv"], }, }); @@ -172,6 +175,12 @@ export default function NewCreateMagazineForm() { const resFile = await uploadMagazineFile(magazineId, formFiles); } } + if (thumbnailImg?.length > 0) { + const formFiles = new FormData(); + + formFiles.append("files", thumbnailImg[0]); + const resFile = await uploadMagazineThumbnail(magazineId, formFiles); + } close(); successSubmit("/admin/magazine"); @@ -308,6 +317,13 @@ export default function NewCreateMagazineForm() {
)); + const handleFileChange = (event: React.ChangeEvent) => { + const selectedFiles = event.target.files; + if (selectedFiles) { + setThumbnailImg(Array.from(selectedFiles)); + } + }; + return ( {errors.slug?.message}

)} +

Thumbnail

+ {thumbnailImg.length > 0 ? ( +
+ thumbnail + +
+ ) : ( + <> + + + )}

Deskripsi

( Upload file dengan format .doc, .docx, .pdf, .ppt, .pptx, - .xlsx, .csv maksimal 100mb.) + maksimal 100mb.)
diff --git a/components/form/magazine/edit-magazine-form.tsx b/components/form/magazine/edit-magazine-form.tsx index e7fb650..e33a466 100644 --- a/components/form/magazine/edit-magazine-form.tsx +++ b/components/form/magazine/edit-magazine-form.tsx @@ -40,6 +40,7 @@ import { getMagazineById, updateMagazine, uploadMagazineFile, + uploadMagazineThumbnail, } from "@/service/magazine"; const CustomEditor = dynamic( @@ -48,6 +49,12 @@ const CustomEditor = dynamic( }, { ssr: false } ); +const ViewEditor = dynamic( + () => { + return import("@/components/editor/view-editor"); + }, + { ssr: false } +); interface FileWithPreview extends File { preview: string; @@ -74,16 +81,18 @@ const createArticleSchema = z.object({ description: z.string().min(2, { message: "Deskripsi harus diisi", }), - rows: z.array( - z.object({ - title: z.string().min(1, { - message: "Main Keyword must be at least 2 characters.", - }), - description: z.string().min(1, { - message: "Title must be at least 2 characters.", - }), - }) - ), + rows: z + .array( + z.object({ + title: z.string().min(1, { + message: "Main Keyword must be at least 2 characters.", + }), + description: z.string().min(1, { + message: "Title must be at least 2 characters.", + }), + }) + ) + .optional(), }); export default function EditMagazineForm(props: { isDetail: boolean }) { @@ -95,6 +104,8 @@ export default function EditMagazineForm(props: { isDetail: boolean }) { const router = useRouter(); const editor = useRef(null); const [files, setFiles] = useState([]); + const [thumbnailImg, setThumbnailImg] = useState([]); + const [prevThumbnail, setPrevThumbnail] = useState(""); const [detailfiles, setDetailFiles] = useState([]); const { getRootProps, getInputProps } = useDropzone({ @@ -116,8 +127,6 @@ export default function EditMagazineForm(props: { isDetail: boolean }) { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [ ".xlsx", ], - "application/vnd.ms-excel": [".xls"], - "text/csv": [".csv"], }, }); @@ -147,6 +156,14 @@ export default function EditMagazineForm(props: { isDetail: boolean }) { const data = res?.data?.data; setValue("title", data?.title); setValue("description", data?.description); + if (res?.data?.data?.thumbnailPath) { + setPrevThumbnail( + res?.data?.data?.thumbnailPath?.split("/")[ + res?.data?.data?.thumbnailPath?.split("/").length - 1 + ] + ); + } + setDetailFiles(data?.files); console.log("datasss", data); @@ -191,13 +208,22 @@ export default function EditMagazineForm(props: { isDetail: boolean }) { const formFiles = new FormData(); for (let i = 0; i < files.length; i++) { + const rows = values?.rows || []; + formFiles.append("files", files[i]); - formFiles.append("title", values.rows[i].title); - formFiles.append("file", values.rows[i].description); + formFiles.append("title", rows[i]?.title || ""); + formFiles.append("file", rows[i]?.description || ""); const resFile = await uploadMagazineFile(String(id), formFiles); } } + if (thumbnailImg?.length > 0) { + const formFiles = new FormData(); + + formFiles.append("files", thumbnailImg[0]); + const resFile = await uploadMagazineThumbnail(String(id), formFiles); + } + close(); successSubmit("/admin/magazine"); }; @@ -377,6 +403,13 @@ export default function EditMagazineForm(props: { isDetail: boolean }) { }); }; + const handleFileChange = (event: React.ChangeEvent) => { + const selectedFiles = event.target.files; + if (selectedFiles) { + setThumbnailImg(Array.from(selectedFiles)); + } + }; + return ( {errors.slug?.message}

)} +

Thumbnail

+ + {prevThumbnail !== "" ? ( +
+ thumbnail + {!isDetail && ( + + )} +
+ ) : thumbnailImg.length > 0 ? ( +
+ thumbnail + +
+ ) : ( + <> + + + )} +

Deskripsi

( - - )} + render={({ field: { onChange, value } }) => + isDetail ? ( + + ) : ( + + ) + } /> {errors?.description && (

@@ -466,7 +553,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {

( Upload file dengan format .doc, .docx, .pdf, .ppt, .pptx, - .xlsx, .csv maksimal 100mb.) + maksimal 100mb.)
diff --git a/components/form/settings/password.tsx b/components/form/settings/password.tsx index a8c1be9..2223aee 100644 --- a/components/form/settings/password.tsx +++ b/components/form/settings/password.tsx @@ -1,108 +1,174 @@ "use client"; -import { FormEvent, Fragment, useEffect, useRef, useState } from "react"; -import { Controller, useForm } from "react-hook-form"; -import * as z from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; +import { useState } from "react"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; -import { Input, Textarea } from "@nextui-org/input"; - -const formSchema = z.object({ - password: z.string().min(2, { - message: "Judul harus diisi", - }), - passwordConf: z.string().min(2, { - message: "Slug harus diisi", - }), -}); +import { Input } from "@nextui-org/input"; +import { EyeFilledIcon, EyeSlashFilledIcon } from "@/components/icons"; +import { Button } from "@nextui-org/button"; +import PasswordChecklist from "react-password-checklist"; export default function PasswordForm() { const MySwal = withReactContent(Swal); + const [isVisible, setIsVisible] = useState([false, false]); - const formOptions = { - resolver: zodResolver(formSchema), + const [passwordConf, setPasswordConf] = useState(""); + const [password, setPassword] = useState(""); + const [isValidPassword, setIsValidPassword] = useState(false); + + const onSubmit = async () => { + const data = { + password: password, + }; + + console.log("data", data); }; - type UserSettingSchema = z.infer; - const { - register, - control, - handleSubmit, - formState: { errors }, - setValue, - getValues, - watch, - setError, - clearErrors, - } = useForm(formOptions); - const onSubmit = async (values: z.infer) => { - console.log("values"); + const generatePassword = () => { + const length = Math.floor(Math.random() * 9) + 8; + + const upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + const lowerCaseChars = "abcdefghijklmnopqrstuvwxyz"; + const numberChars = "0123456789"; + const specialChars = "!@#$%^&*"; + const allChars = + upperCaseChars + lowerCaseChars + numberChars + specialChars; + + let generatedPassword = ""; + + generatedPassword += + upperCaseChars[Math.floor(Math.random() * upperCaseChars.length)]; + generatedPassword += + specialChars[Math.floor(Math.random() * specialChars.length)]; + generatedPassword += + numberChars[Math.floor(Math.random() * numberChars.length)]; + generatedPassword += + lowerCaseChars[Math.floor(Math.random() * lowerCaseChars.length)]; + + for (let i = generatedPassword.length; i < length; i++) { + generatedPassword += + allChars[Math.floor(Math.random() * allChars.length)]; + } + + generatedPassword = generatedPassword + .split("") + .sort(() => 0.5 - Math.random()) + .join(""); + + setPassword(generatedPassword); }; return ( - +

Password

- ( - - )} + setIsVisible([!isVisible[0], isVisible[1]])} + > + {isVisible[0] ? ( + + ) : ( + + )} + + } + value={password} + onChange={(e: any) => { + setPassword(e.target.value.trim()); + }} + onPaste={(e: any) => { + setPassword(e.target.value.trim()); + }} + onCopy={(e: any) => { + setPassword(e.target.value.trim()); + }} /> - {errors?.password && ( -

- {errors.password?.message} -

- )}

Konfirmasi Password

- ( - - )} + setIsVisible([isVisible[0], !isVisible[1]])} + > + {isVisible[1] ? ( + + ) : ( + + )} + + } + type={isVisible[1] ? "text" : "password"} + label="" + placeholder="" + value={passwordConf} + onChange={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} + onPaste={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} + onCopy={(e: any) => { + setPasswordConf(e.target.value.trim()); + }} /> - {errors?.passwordConf && ( -

- {errors.passwordConf?.message} -

- )}
+ + Generate Password + + { + setIsValidPassword(isValid); + }} + className="text-white text-sm my-3" + messages={{ + minLength: "Password must be more than 8 characters", + specialChar: "Password must include a special character", + number: "Password must include a number", + capital: "Password must include an uppercase letter", + match: "Passwords match", + }} + /> + ); } diff --git a/components/form/settings/profile.tsx b/components/form/settings/profile.tsx index 60ed39a..2e9056f 100644 --- a/components/form/settings/profile.tsx +++ b/components/form/settings/profile.tsx @@ -27,6 +27,9 @@ const formSchema = z.object({ nrp: z.string().min(1, { message: "Harus diisi", }), + address: z.string().min(1, { + message: "Harus diisi", + }), gender: z.string().min(1, { message: "Harus diisi", }), @@ -35,9 +38,9 @@ const formSchema = z.object({ }), }); -export default function ProfileForm() { +export default function ProfileForm(props: { profile: any }) { const MySwal = withReactContent(Swal); - + const { profile } = props; const formOptions = { resolver: zodResolver(formSchema), }; @@ -54,8 +57,18 @@ export default function ProfileForm() { clearErrors, } = useForm(formOptions); + useEffect(() => { + setValue("fullname", profile?.fullname); + setValue("username", profile?.username); + setValue("email", profile?.email); + setValue("address", profile?.address); + setValue("nrp", profile?.identityNumber); + setValue("gender", profile?.genderType); + setValue("phoneNumber", profile?.phoneNumber); + }, [profile]); + const onSubmit = async (values: z.infer) => { - console.log("values"); + console.log("values", values); }; return ( @@ -183,6 +196,35 @@ export default function ProfileForm() { )}
+
+

Alamat

+ ( +