QC Profile

# fix bug
- Kapasitas foto profile
- Kapasistas gambar background
- Cek email invalid
- Server action untuk profile (tidak menggunakan API lagi)
### No Issuee
This commit is contained in:
2024-03-12 10:16:04 +08:00
parent 629fd601d4
commit 7baceafa80
37 changed files with 679 additions and 321 deletions

View File

@@ -15,6 +15,7 @@
"@mantine/core": "^6.0.17", "@mantine/core": "^6.0.17",
"@mantine/dates": "^6.0.17", "@mantine/dates": "^6.0.17",
"@mantine/dropzone": "^7.1.3", "@mantine/dropzone": "^7.1.3",
"@mantine/form": "^7.6.1",
"@mantine/hooks": "^6.0.17", "@mantine/hooks": "^6.0.17",
"@mantine/next": "^6.0.17", "@mantine/next": "^6.0.17",
"@mantine/notifications": "^6.0.17", "@mantine/notifications": "^6.0.17",

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -9,7 +9,7 @@ export default async function Page() {
const userId = await User_getUserId(); const userId = await User_getUserId();
const dataUser = await user_getOneById(userId); const dataUser = await user_getOneById(userId);
// await new Promise((a, b) => { // await new Promise((a, b) => {
// setTimeout(a, 1000); // setTimeout(a, 4000);
// }); // });
return ( return (

View File

@@ -23,9 +23,9 @@ export default async function Page({ params }: { params: { id: string } }) {
const dataProfile = await Profile_getOneProfileAndUserById(profileId); const dataProfile = await Profile_getOneProfileAndUserById(profileId);
// console.log(dataProfile) // console.log(dataProfile)
await new Promise((a, b) => { // await new Promise((a, b) => {
setTimeout(a, 1000); // setTimeout(a, 1000);
}); // });
return ( return (
<> <>

View File

@@ -0,0 +1,9 @@
import ComponentGlobal_V2_LoadingPage from "@/app_modules/component_global/loading_page_v2";
export default async function Page() {
return (
<>
<ComponentGlobal_V2_LoadingPage />
</>
);
}

View File

@@ -1,19 +1,51 @@
"use client"; "use client";
import { NotifPeringatan } from "@/app_modules/donasi/component/notifikasi/notif_peringatan"; import {
import { Box, Button, Group } from "@mantine/core"; Box,
import { notifications } from "@mantine/notifications"; Center,
Group,
LoadingOverlay,
Paper,
Skeleton,
Text,
} from "@mantine/core";
export default function ComponentCobaCoba_LoadingPage() {
const listhHuruf = [
{
huruf: "H",
},
{
huruf: "I",
},
{
huruf: "P",
},
{
huruf: "M",
},
{
huruf: "I",
},
];
const customLOader = (
<Center h={"100vh"}>
<Group>
{listhHuruf.map((e, i) => (
<Center key={i} h={"100%"}>
<Skeleton height={50} circle radius={"100%"} />
<Text sx={{ position: "absolute" }} c={"gray.4"} fw={"bold"}>
{e.huruf}
</Text>
</Center>
))}
</Group>
</Center>
);
export default function Coba() {
return ( return (
<> <>
<Box p={"lg"}> <LoadingOverlay visible overlayBlur={2} loader={customLOader} />
<Group position="center">
<Button variant="outline" onClick={() => NotifPeringatan("Coba")}>
Show notification
</Button>
</Group>
</Box>
</> </>
); );
} }

View File

@@ -9,7 +9,6 @@ export async function auth_Logout(kodeId: string) {
name: "ssn", name: "ssn",
value: "", value: "",
maxAge: 0, maxAge: 0,
path: "/dev/auth/login",
}); });
const c = cookies().get("ssn"); const c = cookies().get("ssn");

View File

@@ -20,25 +20,14 @@ export default function User_Logout() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loading2, setLoading2] = useState(false); const [loading2, setLoading2] = useState(false);
const onLogout = async () => {
// await fetch(ApiHipmi.logout)
// .then((res) => res.json())
// .then((val) => {
// if (val.status == 200) {
// setnomor(null);
// setCode(null);
// ComponentGlobal_NotifikasiBerhasil("Anda Berhasil Logout")
// return router.push("/dev/auth/login");
// }
// });
};
async function onClickLogout() { async function onClickLogout() {
// await auth_Logout(kodeId).then((res) => {
// ComponentGlobal_NotifikasiBerhasil("Berhasil Logout");
// });
await auth_Logout(kodeId).then((res) => { await auth_Logout(kodeId).then((res) => {
if (res.status === 200) { if (res.status === 200) {
setKodeId("");
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
router.push(RouterAuth.login) setKodeId("");
} else { } else {
ComponentGlobal_NotifikasiPeringatan(res.message); ComponentGlobal_NotifikasiPeringatan(res.message);
} }

View File

@@ -1,25 +1,43 @@
"use client"; "use client";
import { Box, Center, Group, LoadingOverlay, Skeleton } from "@mantine/core"; import { Box, Center, Group, LoadingOverlay, Skeleton, Text } from "@mantine/core";
export default function ComponentGlobal_V2_LoadingPage() { export default function ComponentGlobal_V2_LoadingPage() {
const customLOader = ( const listhHuruf = [
<Center h={"100vh"}> {
<Group> huruf: "H",
{Array(3) },
.fill(0) {
.map((e, i) => ( huruf: "I",
<Skeleton key={i} height={50} circle mb="xl" /> },
))} {
</Group> huruf: "P",
</Center> },
); {
huruf: "M",
},
{
huruf: "I",
},
];
const customLOader = (
<Center h={"100vh"}>
<Group>
{listhHuruf.map((e, i) => (
<Center key={i} h={"100%"}>
<Skeleton height={50} circle radius={"100%"} />
<Text sx={{ position: "absolute" }} c={"gray.4"} fw={"bold"}>
{e.huruf}
</Text>
</Center>
))}
</Group>
</Center>
);
return ( return (
<> <>
<LoadingOverlay visible overlayBlur={1} loader={customLOader} />
<LoadingOverlay visible overlayBlur={2} loader={customLOader} /> </>
);
</>
);
} }

View File

@@ -59,10 +59,10 @@ export default function Forum_Komentar({ forumId }: { forumId: string }) {
}} }}
/> />
</Paper> </Paper>
<Group position="apart"> <Group position="right">
<ActionIcon> {/* <ActionIcon>
<IconPhotoUp /> <IconPhotoUp />
</ActionIcon> </ActionIcon> */}
<ButtonAction forumId={forumId} /> <ButtonAction forumId={forumId} />
</Group> </Group>
</Stack> </Stack>

View File

@@ -10,7 +10,7 @@ const config = yaml.parse(fs.readFileSync("config.yaml").toString());
export async function User_getUserId() { export async function User_getUserId() {
const c = cookies().get("ssn"); const c = cookies().get("ssn");
if (!c?.value) return redirect(RouterAuth.login); if (!c?.value || c.value === "") return redirect(RouterAuth.login);
const token = JSON.parse( const token = JSON.parse(

View File

@@ -41,6 +41,7 @@ export default function HomeLayout({
const router = useRouter(); const router = useRouter();
const [user, setUser] = useState(dataUser); const [user, setUser] = useState(dataUser);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [loadingUS, setLoadingUS] = useState(false);
const listFooter = [ const listFooter = [
{ {
id: 1, id: 1,
@@ -88,19 +89,26 @@ export default function HomeLayout({
if (user?.Profile === null) { if (user?.Profile === null) {
ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile"); ComponentGlobal_NotifikasiPeringatan("Lengkapi Profile");
} else { } else {
setLoadingUS(true);
// router.push(RouterProfile.katalog + `${user.Profile.id}`); // router.push(RouterProfile.katalog + `${user.Profile.id}`);
router.push(RouterUserSearch.main); router.push(RouterUserSearch.main);
} }
}} }}
> >
<Stack align="center" spacing={0}> {loadingUS ? (
<ActionIcon variant={"transparent"}> <Center>
<IconUserSearch color="white" /> <Loader />
</ActionIcon> </Center>
<Text fz={"xs"} c={"white"}> ) : (
Temukan pengguna <Stack align="center" spacing={0}>
</Text> <ActionIcon variant={"transparent"}>
</Stack> <IconUserSearch color="white" />
</ActionIcon>
<Text fz={"xs"} c={"white"}>
Temukan pengguna
</Text>
</Stack>
)}
</Grid.Col> </Grid.Col>
<Grid.Col <Grid.Col
span={"auto"} span={"auto"}
@@ -113,32 +121,36 @@ export default function HomeLayout({
} }
}} }}
> >
<Stack align="center" spacing={2}> {loading ? (
<ActionIcon variant={"transparent"}> <Center>
{user?.Profile === null ? ( <Loader />
<IconUserCircle color="white" /> </Center>
) : loading ? ( ) : (
<Loader /> <Stack align="center" spacing={2}>
) : ( <ActionIcon variant={"transparent"}>
<Avatar {user?.Profile === null ? (
radius={"xl"} <IconUserCircle color="white" />
size={30} ) : (
sx={{ <Avatar
borderStyle: "solid", radius={"xl"}
borderWidth: "0.5px", size={30}
borderColor: "white", sx={{
}} borderStyle: "solid",
src={ borderWidth: "0.5px",
RouterProfile.api_foto_profile + borderColor: "white",
`${user?.Profile.imagesId}` }}
} src={
/> RouterProfile.api_foto_profile +
)} `${user?.Profile.imagesId}`
</ActionIcon> }
<Text fz={"xs"} c={"white"}> />
Profile )}
</Text> </ActionIcon>
</Stack> <Text fz={"xs"} c={"white"}>
Profile
</Text>
</Stack>
)}
</Grid.Col> </Grid.Col>
</Grid> </Grid>
</Footer> </Footer>

View File

@@ -1,5 +1,6 @@
"use client"; "use client";
import ComponentGlobal_HeaderTamplate from "@/app_modules/component_global/header_tamplate";
import { import {
ActionIcon, ActionIcon,
AppShell, AppShell,
@@ -18,15 +19,16 @@ export default function ProfileLayout({ children }: { children: any }) {
<AppShell <AppShell
header={ header={
<Header height={50} px={"sm"} sx={{borderBlockStyle: "none"}}> // <Header height={50} px={"sm"} sx={{borderBlockStyle: "none"}}>
<Group position="apart" h={50}> // <Group position="apart" h={50}>
<ActionIcon variant="transparent" onClick={() => router.push("/dev/home")}> // <ActionIcon variant="transparent" onClick={() => router.push("/dev/home")}>
<IconArrowLeft /> // <IconArrowLeft />
</ActionIcon> // </ActionIcon>
<Text>Create Profile</Text> // <Text>Create Profile</Text>
<ActionIcon variant="transparent"></ActionIcon> // <ActionIcon variant="transparent"></ActionIcon>
</Group> // </Group>
</Header> // </Header>
<ComponentGlobal_HeaderTamplate title="Buat Profile"/>
} }
> >
{children} {children}

View File

@@ -14,6 +14,7 @@ import {
Paper, Paper,
Select, Select,
Stack, Stack,
Text,
TextInput, TextInput,
} from "@mantine/core"; } from "@mantine/core";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
@@ -22,7 +23,7 @@ import { useRouter } from "next/navigation";
import { useState } from "react"; import { useState } from "react";
import toast from "react-simple-toasts"; import toast from "react-simple-toasts";
import funCreateNewProfile from "../fun/fun_create_profile"; import funCreateNewProfile from "../fun/fun_create_profile";
import { IconCamera } from "@tabler/icons-react"; import { IconAt, IconCamera, IconUpload } from "@tabler/icons-react";
import ComponentKatalog_NotedBox from "../../component/noted_box"; import ComponentKatalog_NotedBox from "../../component/noted_box";
import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime"; import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime";
import { MODEL_PROFILE } from "../model/interface"; import { MODEL_PROFILE } from "../model/interface";
@@ -31,9 +32,9 @@ import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_glob
import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog"; import { RouterProfile } from "@/app/lib/router_hipmi/router_katalog";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { RouterHome } from "@/app/lib/router_hipmi/router_home"; import { RouterHome } from "@/app/lib/router_hipmi/router_home";
import { useForm } from "@mantine/form";
export default function CreateProfile({ userId }: { userId: any }) { export default function CreateProfile({ userId }: { userId: any }) {
const router = useRouter();
const [filePP, setFilePP] = useState<File | null>(null); const [filePP, setFilePP] = useState<File | null>(null);
const [imgPP, setImgPP] = useState<any | null>(); const [imgPP, setImgPP] = useState<any | null>();
const [fileBG, setFileBG] = useState<File | null>(null); const [fileBG, setFileBG] = useState<File | null>(null);
@@ -53,16 +54,32 @@ export default function CreateProfile({ userId }: { userId: any }) {
<Stack> <Stack>
<ComponentKatalog_NotedBox informasi="Upload foto profile anda." /> <ComponentKatalog_NotedBox informasi="Upload foto profile anda." />
<Center> <Center>
<Avatar {imgPP ? (
sx={{ <Paper shadow="lg" radius={"100%"}>
borderStyle: "solid", <Avatar
borderColor: "black", sx={{
borderWidth: "1px", borderStyle: "solid",
}} borderColor: "gray",
src={imgPP ? imgPP : "/aset/global/avatar.png"} borderWidth: "0.5px",
size={150} }}
radius={"100%"} src={imgPP ? imgPP : "/aset/global/avatar.png"}
/> size={150}
radius={"100%"}
/>
</Paper>
) : (
<Paper shadow="lg" radius={"100%"}>
<Avatar
size={150}
radius={"100%"}
sx={{
borderStyle: "solid",
borderColor: "gray",
borderWidth: "0.5px",
}}
/>
</Paper>
)}
</Center> </Center>
<Center> <Center>
<FileButton <FileButton
@@ -71,10 +88,17 @@ export default function CreateProfile({ userId }: { userId: any }) {
const buffer = URL.createObjectURL( const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())]) new Blob([new Uint8Array(await files.arrayBuffer())])
); );
if (files.size > 1000000) {
ComponentGlobal_NotifikasiPeringatan(
"Maaf, Ukuran file terlalu besar, maximum 1mb",
3000
);
} else {
setImgPP(buffer);
setFilePP(files);
}
// console.log(buffer, "ini buffer"); // console.log(buffer, "ini buffer");
// console.log(files, " ini file"); // console.log(files, " ini file");
setImgPP(buffer);
setFilePP(files);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -104,13 +128,25 @@ export default function CreateProfile({ userId }: { userId: any }) {
<AspectRatio ratio={16 / 9}> <AspectRatio ratio={16 / 9}>
<Paper <Paper
radius={"md"} radius={"md"}
sx={{ withBorder
borderStyle: "solid", shadow="lg"
borderColor: "black", bg={"gray.2"}
borderWidth: "1px", // sx={{
}} // borderStyle: "solid",
// borderColor: "black",
// borderWidth: "1px",
// }}
> >
<Image alt="Foto" src={imgBG ? imgBG : "/aset/no-img.png"} /> {imgBG ? (
<Image alt="Foto" src={imgBG ? imgBG : "/aset/no-img.png"} />
) : (
<Stack align="center">
<IconUpload color="gray" />
<Text fz={"xs"} c={"gray"}>
Upload Background
</Text>
</Stack>
)}
</Paper> </Paper>
</AspectRatio> </AspectRatio>
@@ -121,10 +157,17 @@ export default function CreateProfile({ userId }: { userId: any }) {
const buffer = URL.createObjectURL( const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())]) new Blob([new Uint8Array(await files.arrayBuffer())])
); );
if (files.size > 1000000) {
ComponentGlobal_NotifikasiPeringatan(
"Maaf, Ukuran file terlalu besar, maximum 1mb",
3000
);
} else {
setImgBG(buffer);
setFileBG(files);
}
// console.log(buffer, "ini buffer"); // console.log(buffer, "ini buffer");
// console.log(files, " ini file"); // console.log(files, " ini file");
setImgBG(buffer);
setFileBG(files);
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -148,96 +191,139 @@ export default function CreateProfile({ userId }: { userId: any }) {
</Stack> </Stack>
</Box> </Box>
<TextInput <Stack mb={"lg"}>
label="Nama" <TextInput
onChange={(val) => { withAsterisk
setValue({ label="Nama"
...value, placeholder="Nama lengkap"
name: val.target.value, onChange={(val) => {
}); setValue({
}} ...value,
/> name: val.target.value,
<TextInput });
label="Email" }}
onChange={(val) => { />
setValue({ <TextInput
...value, withAsterisk
email: val.target.value, icon={<IconAt size={15} />}
}); label="Email"
}} placeholder="Contoh: User@gmail.com"
/> error={
<TextInput value.email.length > 0 && !value.email.includes("@")
label="Alamat" ? "Invalid email"
onChange={(val) => { : ""
setValue({ }
...value, onChange={(val) => {
alamat: val.target.value, setValue({
}); ...value,
}} email: val.target.value,
/> });
<Select }}
label="Jenis Kelamin" />
data={[ <TextInput
{ value: "Laki-laki", label: "Laki-laki" }, withAsterisk
{ value: "Perempuan", label: "Perempuan" }, label="Alamat"
]} placeholder="Alamat lengkap"
onChange={(val) => { onChange={(val) => {
setValue({ setValue({
...value, ...value,
jenisKelamin: val as string, alamat: val.target.value,
}); });
}} }}
/> />
<Button <Select
mt={"md"} withAsterisk
radius={50} label="Jenis Kelamin"
bg={Warna.hijau_muda} placeholder="Pilih satu"
color="green" data={[
onClick={() => { value: "Laki-laki", label: "Laki-laki" },
onSubmit(router, value as any, userId, filePP as any, fileBG as any) { value: "Perempuan", label: "Perempuan" },
} ]}
> onChange={(val) => {
Simpan setValue({
</Button> ...value,
jenisKelamin: val as string,
});
}}
/>
<ButtonAction
value={value as any}
userId={userId}
filePP={filePP as any}
fileBg={fileBG as any}
/>
</Stack>
</Stack> </Stack>
</> </>
); );
} }
async function onSubmit( function ButtonAction({
router: AppRouterInstance, value,
value: MODEL_PROFILE, userId,
userId: string, filePP,
filePP: FormData, fileBg,
fileBg: FormData }: {
) { value: MODEL_PROFILE;
const body = { userId: string;
userId: userId, filePP: FormData;
name: value.name, fileBg: FormData;
email: value.email, }) {
alamat: value.alamat, const router = useRouter();
jenisKelamin: value.jenisKelamin, const [loading, setLoading] = useState(false);
};
if(_.values(body).includes("")) return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data")
const gambarPP = new FormData(); async function onSubmit() {
gambarPP.append("filePP", filePP as any); const body = {
userId: userId,
name: value.name,
email: value.email,
alamat: value.alamat,
jenisKelamin: value.jenisKelamin,
};
if (_.values(body).includes(""))
return ComponentGlobal_NotifikasiPeringatan("Lengkapi Data");
if (!body.email.includes("@"))
return ComponentGlobal_NotifikasiPeringatan("Invalid Email");
const gambarBG = new FormData(); const gambarPP = new FormData();
gambarBG.append("fileBG", fileBg as any); gambarPP.append("filePP", filePP as any);
const gambarBG = new FormData();
gambarBG.append("fileBG", fileBg as any);
if(!gambarPP) return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile") if (!gambarPP)
if(!gambarBG) return ComponentGlobal_NotifikasiPeringatan("Lengkapi background profile") return ComponentGlobal_NotifikasiPeringatan("Lengkapi foto profile");
if (!gambarBG)
return ComponentGlobal_NotifikasiPeringatan(
"Lengkapi background profile"
);
await funCreateNewProfile(body as any, gambarPP, gambarBG).then((res) => {
if (res.status === 201) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Profile", 3000);
router.push(RouterHome.main_home);
} else {
ComponentGlobal_NotifikasiGagal(res.message);
}
});
}
await funCreateNewProfile(body as any, gambarPP, gambarBG).then((res) => { return (
if (res.status === 201) { <>
ComponentGlobal_NotifikasiBerhasil("Berhasil Membuat Profile") <Button
router.push(RouterHome.main_home); loading={loading ? true : false}
} else { loaderPosition="center"
ComponentGlobal_NotifikasiGagal(res.message); mt={"md"}
} radius={50}
}); bg={Warna.hijau_muda}
color="green"
onClick={() => {
onSubmit();
}}
>
Simpan
</Button>
</>
);
} }

View File

@@ -23,15 +23,19 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
//Get data profile //Get data profile
const [dataProfile, setDataProfile] = useState(data); const [dataProfile, setDataProfile] = useState(data);
const [loading, setLoading] = useState(false);
async function onUpdate() { async function onUpdate() {
const body = dataProfile; const body = dataProfile;
// console.log(body)
if (_.values(body).includes("")) return toast("Lengkapi data"); if (_.values(body).includes("")) return toast("Lengkapi data");
await Profile_funEditById(body).then((res) => { await Profile_funEditById(body).then((res) => {
if (res.status === 200) { if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
setTimeout(() => router.back(), 1000) setTimeout(() => router.back(), 1000);
} else { } else {
ComponentGlobal_NotifikasiGagal(res.message); ComponentGlobal_NotifikasiGagal(res.message);
} }
@@ -47,18 +51,42 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
return ( return (
<> <>
{/* <pre>{JSON.stringify(dataProfile, null, 2)}</pre> */}
<Stack px={"sm"}> <Stack px={"sm"}>
<TextInput <TextInput
label="Username" withAsterisk
label="Nomor"
disabled disabled
value={dataProfile.User.username} value={dataProfile?.User?.nomor}
/> />
<TextInput label="Nomor" disabled value={dataProfile.User.nomor} />
<TextInput <TextInput
withAsterisk
label="Username"
error={
data?.User?.username?.length < 5
? "Username minimal 5 karakter"
: ""
}
disabled
value={dataProfile?.User?.username}
onChange={(val) => {
// const dataUsername = _.clone(dataProfile)
setDataProfile({
...(dataProfile as any),
User: {
username: val.target.value,
},
});
}}
/>
<TextInput
withAsterisk
label="Nama" label="Nama"
placeholder="Nama" placeholder="Nama"
value={dataProfile.name} value={dataProfile?.name}
onChange={(val) => { onChange={(val) => {
setDataProfile({ setDataProfile({
...dataProfile, ...dataProfile,
@@ -68,9 +96,15 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
/> />
<TextInput <TextInput
withAsterisk
label="Email" label="Email"
placeholder="email" placeholder="email"
value={dataProfile.email} error={
dataProfile?.email?.length > 0 && !dataProfile?.email.includes("@")
? "Invalid email"
: ""
}
value={dataProfile?.email}
onChange={(val) => { onChange={(val) => {
setDataProfile({ setDataProfile({
...dataProfile, ...dataProfile,
@@ -80,6 +114,7 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
/> />
<TextInput <TextInput
withAsterisk
label="Alamat" label="Alamat"
placeholder="alamat" placeholder="alamat"
value={dataProfile.alamat} value={dataProfile.alamat}
@@ -92,8 +127,9 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
/> />
<Select <Select
withAsterisk
label="Jenis Kelamin" label="Jenis Kelamin"
value={dataProfile.jenisKelamin} value={dataProfile?.jenisKelamin}
data={[ data={[
{ value: "Laki-laki", label: "Laki-laki" }, { value: "Laki-laki", label: "Laki-laki" },
{ value: "Perempuan", label: "Perempuan" }, { value: "Perempuan", label: "Perempuan" },
@@ -101,7 +137,7 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
onChange={(val: any) => { onChange={(val: any) => {
setDataProfile({ setDataProfile({
...dataProfile, ...dataProfile,
jenisKelamin: val jenisKelamin: val,
}); });
}} }}
/> />
@@ -111,6 +147,8 @@ export default function EditProfile({ data }: { data: MODEL_PROFILE }) {
radius={50} radius={50}
bg={Warna.biru} bg={Warna.biru}
color="cyan" color="cyan"
loading={loading ? true : false}
loaderPosition="center"
onClick={() => onUpdate()} onClick={() => onUpdate()}
> >
Update Update

View File

@@ -5,6 +5,17 @@ import { MODEL_PROFILE } from "../../model/interface";
import { revalidatePath } from "next/cache"; import { revalidatePath } from "next/cache";
export async function Profile_funEditById(data: MODEL_PROFILE) { export async function Profile_funEditById(data: MODEL_PROFILE) {
// console.log(data);
const cekEmail = await prisma.profile.findUnique({
where: {
email: data.email,
},
});
if (cekEmail && cekEmail.id != data.id)
return { status: 400, message: "Email sudah digunakan" };
const updt = await prisma.profile.update({ const updt = await prisma.profile.update({
where: { where: {
id: data.id, id: data.id,

View File

@@ -6,35 +6,18 @@ import _ from "lodash";
import { v4 } from "uuid"; import { v4 } from "uuid";
import { revalidatePath } from "next/cache"; import { revalidatePath } from "next/cache";
export async function Profile_funUpdateBackground(profileId: string, file: FormData) { export async function Profile_funUpdateBackground(
const findProfile = await prisma.profile.findFirst({ profileId: string,
where: { file: FormData
id: profileId, ) {
},
});
const findBackground = await prisma.imagesBackground.findFirst({
where: {
id: findProfile?.imagesBackgroundId as string,
},
select: {
url: true,
},
});
if (!findBackground) return { status: 400, message: "Foto tidak ditemukan" };
if (findBackground) fs.unlinkSync(`./public/profile/background/${findBackground.url}`);
const gambarBackground: any = file.get("file"); const gambarBackground: any = file.get("file");
const fileName = gambarBackground.name; const fileName = gambarBackground.name;
const fileExtension = _.lowerCase(gambarBackground.name.split(".").pop()); const fileExtension = _.lowerCase(gambarBackground.name.split(".").pop());
const randomName = v4(fileName) + "." + fileExtension; const fRandomName = v4(fileName) + "." + fileExtension;
const uploadBG = await prisma.imagesBackground.update({ const uploadBG = await prisma.imagesBackground.create({
where: {
id: findProfile?.imagesBackgroundId as string,
},
data: { data: {
url: randomName, url: fRandomName,
label: "PROFILE_BACKGROUND", label: "PROFILE_BACKGROUND",
}, },
select: { select: {
@@ -43,13 +26,77 @@ export async function Profile_funUpdateBackground(profileId: string, file: FormD
}, },
}); });
if (!uploadBG) return { status: 400, message: "Gagal upload foto background" }; if (!uploadBG)
const uploadPP_Folder = Buffer.from(await gambarBackground.arrayBuffer()); return { status: 400, message: "Gagal upload gambar background" };
fs.writeFileSync(`./public/profile/background/${uploadBG.url}`, uploadPP_Folder); const uploadBG_Folder = Buffer.from(await gambarBackground.arrayBuffer());
fs.writeFileSync(
`./public/profile/background/${uploadBG.url}`,
uploadBG_Folder
);
revalidatePath("/dev/katalog");
const updateBackground = await prisma.profile.update({
where: {
id: profileId,
},
data: {
imagesBackgroundId: uploadBG.id,
},
});
if (!updateBackground)
return { status: 400, message: "Gagal update gambar background" };
revalidatePath("/dev/katalog"); revalidatePath("/dev/katalog");
return { return {
status: 200, status: 200,
message: "Update berhasil", message: "Update berhasil",
}; };
// const findProfile = await prisma.profile.findFirst({
// where: {
// id: profileId,
// },
// });
// const findBackground = await prisma.imagesBackground.findFirst({
// where: {
// id: findProfile?.imagesBackgroundId as string,
// },
// select: {
// url: true,
// },
// });
// if (!findBackground) return { status: 400, message: "Foto tidak ditemukan" };
// if (findBackground) fs.unlinkSync(`./public/profile/background/${findBackground.url}`);
// const gambarBackground: any = file.get("file");
// const fileName = gambarBackground.name;
// const fileExtension = _.lowerCase(gambarBackground.name.split(".").pop());
// const randomName = v4(fileName) + "." + fileExtension;
// const uploadBG = await prisma.imagesBackground.update({
// where: {
// id: findProfile?.imagesBackgroundId as string,
// },
// data: {
// url: randomName,
// label: "PROFILE_BACKGROUND",
// },
// select: {
// id: true,
// url: true,
// },
// });
// if (!uploadBG) return { status: 400, message: "Gagal upload foto background" };
// const uploadBG_Folder = Buffer.from(await gambarBackground.arrayBuffer());
// fs.writeFileSync(`./public/profile/background/${uploadBG.url}`, uploadBG_Folder);
// revalidatePath("/dev/katalog");
// return {
// status: 200,
// message: "Update berhasil",
// };
} }

View File

@@ -7,34 +7,14 @@ import { v4 } from "uuid";
import { revalidatePath } from "next/cache"; import { revalidatePath } from "next/cache";
export async function Profile_funUpdateFoto(profileId: string, file: FormData) { export async function Profile_funUpdateFoto(profileId: string, file: FormData) {
const findProfile = await prisma.profile.findFirst({
where: {
id: profileId,
},
});
const findFoto = await prisma.images.findFirst({
where: {
id: findProfile?.imagesId as string,
},
select: {
url: true,
},
});
if (!findFoto) return { status: 400, message: "Foto tidak ditemukan" };
if (findFoto) fs.unlinkSync(`./public/profile/foto/${findFoto.url}`);
const gambarProfile: any = file.get("file"); const gambarProfile: any = file.get("file");
const fileName = gambarProfile.name; const fileName = gambarProfile.name;
const fileExtension = _.lowerCase(gambarProfile.name.split(".").pop()); const fileExtension = _.lowerCase(gambarProfile.name.split(".").pop());
const randomName = v4(fileName) + "." + fileExtension; const fRandomName = v4(fileName) + "." + fileExtension;
const uploadPP = await prisma.images.update({ const uploadPP = await prisma.images.create({
where: {
id: findProfile?.imagesId as string,
},
data: { data: {
url: randomName, url: fRandomName,
label: "PROFILE_FOTO", label: "PROFILE_FOTO",
}, },
select: { select: {
@@ -46,10 +26,69 @@ export async function Profile_funUpdateFoto(profileId: string, file: FormData) {
if (!uploadPP) return { status: 400, message: "Gagal upload foto profile" }; if (!uploadPP) return { status: 400, message: "Gagal upload foto profile" };
const uploadPP_Folder = Buffer.from(await gambarProfile.arrayBuffer()); const uploadPP_Folder = Buffer.from(await gambarProfile.arrayBuffer());
fs.writeFileSync(`./public/profile/foto/${uploadPP.url}`, uploadPP_Folder); fs.writeFileSync(`./public/profile/foto/${uploadPP.url}`, uploadPP_Folder);
const updateProfile = await prisma.profile.update({
where: {
id: profileId,
},
data: {
imagesId: uploadPP.id,
},
});
if (!updateProfile) return { status: 400, message: "Gagal update foto" };
revalidatePath("/dev/katalog"); revalidatePath("/dev/katalog");
return { return {
status: 200, status: 200,
message: "Update berhasil", message: "Update berhasil",
}; };
// const findProfile = await prisma.profile.findFirst({
// where: {
// id: profileId,
// },
// });
// const findFoto = await prisma.images.findFirst({
// where: {
// id: findProfile?.imagesId as string,
// },
// select: {
// url: true,
// },
// });
// if (!findFoto) return { status: 400, message: "Foto tidak ditemukan" };
// if (findFoto) fs.unlinkSync(`./public/profile/foto/${findFoto.url}`);
// const gambarProfile: any = file.get("file");
// const fileName = gambarProfile.name;
// const fileExtension = _.lowerCase(gambarProfile.name.split(".").pop());
// const randomName = v4(fileName) + "." + fileExtension;
// const uploadPP = await prisma.images.update({
// where: {
// id: findProfile?.imagesId as string,
// },
// data: {
// url: randomName,
// label: "PROFILE_FOTO",
// },
// select: {
// id: true,
// url: true,
// },
// });
// if (!uploadPP) return { status: 400, message: "Gagal upload foto profile" };
// const uploadPP_Folder = Buffer.from(await gambarProfile.arrayBuffer());
// fs.writeFileSync(`./public/profile/foto/${uploadPP.url}`, uploadPP_Folder);
// revalidatePath("/dev/katalog");
// return {
// status: 200,
// message: "Update berhasil",
// };
} }

View File

@@ -2,7 +2,7 @@ import ProfileLayout from "./create/layout";
import CreateProfile from "./create/view"; import CreateProfile from "./create/view";
import EditProfileLayout from "./edit/layout"; import EditProfileLayout from "./edit/layout";
import EditProfileView from "./edit/view"; import EditProfileView from "./edit/view";
import UploadFotoProfile from "./upload/foto_profile/view"; import UploadFotoProfile from "./upload/foto_profile";
import UploadFotoProfileLayout from "./upload/foto_profile/layout" import UploadFotoProfileLayout from "./upload/foto_profile/layout"
import ProfileView from "./main/view"; import ProfileView from "./main/view";
import Profile_UpdateFotoBackground from "./upload/foto_background"; import Profile_UpdateFotoBackground from "./upload/foto_background";

View File

@@ -40,6 +40,10 @@ export default function ProfileView({
userLoginId: string; userLoginId: string;
}) { }) {
const router = useRouter(); const router = useRouter();
const [loadingPP, setLoadingPP] = useState(false);
const [loadingBG, setLoadingBG] = useState(false);
const [loadingEdit, setLoadingEdit] = useState(false);
// const [data, setData] = useState(profile); // const [data, setData] = useState(profile);
// useShallowEffect(() => { // useShallowEffect(() => {
// funGetUserProfile(user.id ?? "").then(setProfile as any); // funGetUserProfile(user.id ?? "").then(setProfile as any);
@@ -49,7 +53,7 @@ export default function ProfileView({
return ( return (
<> <>
{/* <pre>{JSON.stringify(profile, null,2)}</pre> */} {/* <pre>{JSON.stringify(profile, null,2)}</pre> */}
<Paper p={"sm"} bg={"gray.1"} shadow="lg" withBorder> <Paper px={"md"} py={"sm"} bg={"gray.1"} shadow="lg" withBorder>
{/* Background dan foto */} {/* Background dan foto */}
{/* Upload Background Profile */} {/* Upload Background Profile */}
@@ -57,12 +61,14 @@ export default function ProfileView({
<AspectRatio ratio={16 / 9}> <AspectRatio ratio={16 / 9}>
<Paper radius={"sm"} shadow="md"> <Paper radius={"sm"} shadow="md">
<Image <Image
radius={"sm"} mah={"100%"}
height={210} maw={"100%"}
alt="" alt="Background"
src={ src={
RouterProfile.api_url_background + profile?.ImagesBackground.url
`${profile?.ImagesBackground.url}` ? RouterProfile.api_url_background +
`${profile?.ImagesBackground.url}`
: "/aset/no-image.png"
} }
/> />
</Paper> </Paper>
@@ -72,19 +78,21 @@ export default function ProfileView({
{profile?.User.id === userLoginId ? ( {profile?.User.id === userLoginId ? (
<Center> <Center>
<ActionIcon <ActionIcon
ml={{base: 300, sm: 500, md: 900, lg: 1000}} loading={loadingBG ? true : false}
ml={{ base: 300, sm: 500, md: 900, lg: 1000 }}
mt={-10} mt={-10}
bg={"gray.5"} bg={"gray.5"}
variant="transparent" variant="transparent"
radius={50} radius={50}
onClick={() => onClick={() => {
setLoadingBG(true);
router.push( router.push(
RouterProfile.update_foto_background + `${profile.id}` RouterProfile.update_foto_background + `${profile.id}`
) );
} }}
sx={{ sx={{
position: "relative", position: "relative",
// zIndex: 2, color: "gray",
border: "1px", border: "1px",
borderStyle: "solid", borderStyle: "solid",
}} }}
@@ -110,10 +118,15 @@ export default function ProfileView({
bg={"gray.2"} bg={"gray.2"}
sx={{ sx={{
borderStyle: "solid", borderStyle: "solid",
borderColor: "black", borderColor: "gray",
borderWidth: "1px", borderWidth: "0.5px",
}} }}
src={RouterProfile.api_url_foto + `${profile?.ImageProfile.url}`} src={
profile?.ImageProfile?.url
? RouterProfile.api_url_foto +
`${profile?.ImageProfile.url}`
: "/aset/global/avatar.png"
}
size={100} size={100}
radius={"100%"} radius={"100%"}
/> />
@@ -124,16 +137,18 @@ export default function ProfileView({
{profile?.User.id === userLoginId ? ( {profile?.User.id === userLoginId ? (
<Center> <Center>
<ActionIcon <ActionIcon
loading={loadingPP ? true : false}
mr={-70} mr={-70}
mt={15} mt={15}
variant="transparent" variant="transparent"
bg={"gray.5"} bg={"gray.5"}
radius={50} radius={50}
onClick={() => onClick={() => {
setLoadingPP(true);
router.push( router.push(
RouterProfile.update_foto_profile + `${profile.id}` RouterProfile.update_foto_profile + `${profile.id}`
) );
} }}
sx={{ sx={{
position: "relative", position: "relative",
border: "1px", border: "1px",
@@ -150,30 +165,47 @@ export default function ProfileView({
{/* Username dan Nama */} {/* Username dan Nama */}
<Grid>
<Grid.Col
span={"auto"}
pt={profile?.User.id === userLoginId ? 10 : 50}
>
<Stack spacing={0}>
<Text fz={"lg"} fw={"bold"} lineClamp={1}>
{profile?.name}
</Text>
<Text fz={"xs"} c={"dark.3"}>
@{profile?.User?.username}
</Text>
</Stack>
</Grid.Col>
<Grid.Col span={"content"}>
{profile?.User.id === userLoginId ? (
<ActionIcon
loading={loadingEdit ? true : false}
variant="transparent"
onClick={() => {
setLoadingEdit(true);
router.push(RouterProfile.edit + `${profile.id}`);
}}
>
<IconEditCircle color={Warna.hijau_muda} />
</ActionIcon>
) : (
""
)}
</Grid.Col>
</Grid>
<Group position="apart" pt={profile?.User.id === userLoginId ? 0 : "xl" }> {/* <Group
<Flex direction={"column"} mt={"lg"}> position="apart"
<Text fz={"lg"} fw={"bold"}> pt={profile?.User.id === userLoginId ? 0 : "xl"}
{profile?.name} >
</Text> <Flex direction={"column"} mt={"lg"}></Flex>
<Text fz={"xs"}>@{profile?.User?.username}</Text> </Group> */}
</Flex>
{profile?.User.id === userLoginId ? (
<ActionIcon
variant="transparent"
onClick={() => {
router.push(RouterProfile.edit + `${profile.id}`);
}}
>
<IconEditCircle color={Warna.hijau_muda} />
</ActionIcon>
) : (
""
)}
</Group>
{/* Info user: nomor, email dll */} {/* Info user: nomor, email dll */}
<Stack spacing={"xs"} pt={"lg"}> <Stack spacing={"xs"} pt={"lg"}>
<Grid> <Grid>
<Grid.Col span={"content"}> <Grid.Col span={"content"}>
<IconAddressBook /> <IconAddressBook />

View File

@@ -33,6 +33,7 @@ export default function Profile_UpdateFotoBackground({
const [profile, setProfile] = useState(dataProfile); const [profile, setProfile] = useState(dataProfile);
const [file, setFile] = useState<File | null>(null); const [file, setFile] = useState<File | null>(null);
const [image, setImage] = useState<any | null>(null); const [image, setImage] = useState<any | null>(null);
const [loading, setLoading] = useState(false);
return ( return (
<> <>
@@ -57,10 +58,15 @@ export default function Profile_UpdateFotoBackground({
const buffer = URL.createObjectURL( const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())]) new Blob([new Uint8Array(await files.arrayBuffer())])
); );
// console.log(buffer, "ini buffer"); if (files.size > 1000000) {
// console.log(files, " ini file"); ComponentGlobal_NotifikasiPeringatan(
setImage(buffer); "Maaf, Ukuran file terlalu besar, maximum 1mb",
setFile(files); 3000
);
} else {
setImage(buffer);
setFile(files);
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -85,10 +91,13 @@ export default function Profile_UpdateFotoBackground({
</Paper> </Paper>
<Button <Button
disabled={file ? false : true}
loading={loading ? true : false}
loaderPosition="center"
radius={"xl"} radius={"xl"}
onClick={() => onUpdate(router, profile.id, file as any)} onClick={() => onUpdate(router, profile.id, file as any, setLoading)}
> >
Simpan Update
</Button> </Button>
</Stack> </Stack>
</> </>
@@ -98,13 +107,15 @@ export default function Profile_UpdateFotoBackground({
async function onUpdate( async function onUpdate(
router: AppRouterInstance, router: AppRouterInstance,
profileId: string, profileId: string,
file: FormData file: FormData,
setLoading: any
) { ) {
const gambar = new FormData(); const gambar = new FormData();
gambar.append("file", file as any); gambar.append("file", file as any);
await Profile_funUpdateBackground(profileId, gambar).then((res) => { await Profile_funUpdateBackground(profileId, gambar).then((res) => {
if (res.status === 200) { if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
router.back(); router.back();
} else { } else {

View File

@@ -19,6 +19,7 @@ import { useRouter } from "next/navigation";
import { Profile_funUpdateFoto } from "../../fun/update/fun_update_foto_profile"; import { Profile_funUpdateFoto } from "../../fun/update/fun_update_foto_profile";
import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil"; import { ComponentGlobal_NotifikasiBerhasil } from "@/app_modules/component_global/notif_global/notifikasi_berhasil";
import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal"; import { ComponentGlobal_NotifikasiGagal } from "@/app_modules/component_global/notif_global/notifikasi_gagal";
import { ComponentGlobal_NotifikasiPeringatan } from "@/app_modules/component_global/notif_global/notifikasi_peringatan";
export default function UploadFotoProfile({ export default function UploadFotoProfile({
dataProfile, dataProfile,
@@ -29,6 +30,7 @@ export default function UploadFotoProfile({
const [profile, setProfile] = useState(dataProfile); const [profile, setProfile] = useState(dataProfile);
const [file, setFile] = useState<File | null>(null); const [file, setFile] = useState<File | null>(null);
const [image, setImage] = useState<any | null>(null); const [image, setImage] = useState<any | null>(null);
const [loading, setLoading] = useState(false);
return ( return (
<> <>
@@ -52,10 +54,15 @@ export default function UploadFotoProfile({
const buffer = URL.createObjectURL( const buffer = URL.createObjectURL(
new Blob([new Uint8Array(await files.arrayBuffer())]) new Blob([new Uint8Array(await files.arrayBuffer())])
); );
// console.log(buffer, "ini buffer"); if (files.size > 1000000) {
// console.log(files, " ini file"); ComponentGlobal_NotifikasiPeringatan(
setImage(buffer); "Maaf, Ukuran file terlalu besar, maximum 1mb",
setFile(files); 3000
);
} else {
setImage(buffer);
setFile(files);
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@@ -80,10 +87,15 @@ export default function UploadFotoProfile({
</Paper> </Paper>
<Button <Button
disabled={file ? false : true}
loading={loading ? true : false}
loaderPosition="center"
radius={"xl"} radius={"xl"}
onClick={() => onUpdate(router, profile.id, file as any)} onClick={() => {
onUpdate(router, profile.id, file as any, setLoading);
}}
> >
Simpan Update
</Button> </Button>
</Stack> </Stack>
</> </>
@@ -93,13 +105,15 @@ export default function UploadFotoProfile({
async function onUpdate( async function onUpdate(
router: AppRouterInstance, router: AppRouterInstance,
profileId: string, profileId: string,
file: FormData file: FormData,
setLoading: any
) { ) {
const gambar = new FormData(); const gambar = new FormData();
gambar.append("file", file as any); gambar.append("file", file as any);
await Profile_funUpdateFoto(profileId, gambar).then((res) => { await Profile_funUpdateFoto(profileId, gambar).then((res) => {
if (res.status === 200) { if (res.status === 200) {
setLoading(true);
ComponentGlobal_NotifikasiBerhasil(res.message); ComponentGlobal_NotifikasiBerhasil(res.message);
router.back(); router.back();
} else { } else {

View File

@@ -20,6 +20,7 @@ import { useState } from "react";
import { UserSearch_searchByName } from "../fun/search/fun_search_by_name"; import { UserSearch_searchByName } from "../fun/search/fun_search_by_name";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import ComponentGlobal_MaintenanceInformation from "@/app_modules/component_global/maintenance_information"; import ComponentGlobal_MaintenanceInformation from "@/app_modules/component_global/maintenance_information";
import ComponentGlobal_V2_LoadingPage from "@/app_modules/component_global/loading_page_v2";
export default function UserSearch_MainView({ export default function UserSearch_MainView({
listUser, listUser,
@@ -28,6 +29,7 @@ export default function UserSearch_MainView({
}) { }) {
const router = useRouter(); const router = useRouter();
const [user, setUser] = useState(listUser); const [user, setUser] = useState(listUser);
const [loading, setLoading] = useState(false);
async function onSearch(name: string) { async function onSearch(name: string) {
await UserSearch_searchByName(name).then((res) => setUser(res as any)); await UserSearch_searchByName(name).then((res) => setUser(res as any));
@@ -41,6 +43,8 @@ export default function UserSearch_MainView({
// </> // </>
// ); // );
if(loading) return <ComponentGlobal_V2_LoadingPage/>
return ( return (
<> <>
<Box> <Box>
@@ -60,11 +64,11 @@ export default function UserSearch_MainView({
"" ""
) : ( ) : (
<Stack key={e.id} spacing={"xs"} mt={"xs"}> <Stack key={e.id} spacing={"xs"} mt={"xs"}>
<Grid > <Grid>
<Grid.Col span={2}> <Grid.Col span={2}>
<Center h={"100%"}> <Center h={"100%"}>
<Avatar <Avatar
sx={{borderStyle: "solid", borderWidth: "0.5px"}} sx={{ borderStyle: "solid", borderWidth: "0.5px" }}
radius={"xl"} radius={"xl"}
size={"md"} size={"md"}
src={ src={
@@ -76,7 +80,7 @@ export default function UserSearch_MainView({
</Grid.Col> </Grid.Col>
<Grid.Col span={"auto"}> <Grid.Col span={"auto"}>
<Stack spacing={0}> <Stack spacing={0}>
<Text fw={"bold"} truncate> <Text fw={"bold"} lineClamp={1}>
{e?.Profile?.name} {e?.Profile?.name}
</Text> </Text>
<Text fz={"sm"} fs={"italic"}> <Text fz={"sm"} fs={"italic"}>
@@ -88,11 +92,12 @@ export default function UserSearch_MainView({
<Center h={"100%"}> <Center h={"100%"}>
<ActionIcon <ActionIcon
variant="transparent" variant="transparent"
onClick={() => onClick={() => {
setLoading(true);
router.push( router.push(
RouterProfile.katalog + `${e?.Profile?.id}` RouterProfile.katalog + `${e?.Profile?.id}`
) );
} }}
> >
<IconChevronRight /> <IconChevronRight />
</ActionIcon> </ActionIcon>

View File

@@ -322,6 +322,14 @@
dependencies: dependencies:
react-dropzone-esm "15.0.1" react-dropzone-esm "15.0.1"
"@mantine/form@^7.6.1":
version "7.6.1"
resolved "https://registry.yarnpkg.com/@mantine/form/-/form-7.6.1.tgz#b98307c91ae8fe5559590d2eefe6c60c22868330"
integrity sha512-S0pdvFohRX3ahzhrCGM+d2sBaSHH88UkQhbzyOAGJ7xqNjPJ11Bh/xb4Mc+NXXxaq9MjPrRVe6fgpKJtXszBpQ==
dependencies:
fast-deep-equal "^3.1.3"
klona "^2.0.6"
"@mantine/hooks@^6.0.17": "@mantine/hooks@^6.0.17":
version "6.0.21" version "6.0.21"
resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-6.0.21.tgz#bc009d8380ad18455b90f3ddaf484de16a13da95" resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-6.0.21.tgz#bc009d8380ad18455b90f3ddaf484de16a13da95"
@@ -2940,6 +2948,11 @@ keyv@^4.5.3:
dependencies: dependencies:
json-buffer "3.0.1" json-buffer "3.0.1"
klona@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==
language-subtag-registry@^0.3.20: language-subtag-registry@^0.3.20:
version "0.3.22" version "0.3.22"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"