From e3d909e7602a99938820bbf6bee6bda41cd31474 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 28 Nov 2025 15:31:10 +0800 Subject: [PATCH 1/6] fix ganti role, user menu access ikut ke create --- .../user&role/_com/getMenuIdByRole.ts | 25 +++++++++++++++++++ src/app/api/[[...slugs]]/_lib/user/updt.ts | 22 ++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/app/admin/(dashboard)/user&role/_com/getMenuIdByRole.ts diff --git a/src/app/admin/(dashboard)/user&role/_com/getMenuIdByRole.ts b/src/app/admin/(dashboard)/user&role/_com/getMenuIdByRole.ts new file mode 100644 index 00000000..07524555 --- /dev/null +++ b/src/app/admin/(dashboard)/user&role/_com/getMenuIdByRole.ts @@ -0,0 +1,25 @@ +// src/app/admin/_com/getMenuIdsByRoleId.ts +import { navBar, role1, role2, role3 } from '@/app/admin/_com/list_PageAdmin'; + +/** + * Mengembalikan daftar ID menu (string[]) berdasarkan roleId + */ +export function getMenuIdsByRoleId(roleId: string | number): string[] { + const id = typeof roleId === 'string' ? parseInt(roleId, 10) : roleId; + + switch (id) { + case 0: + // Asumsikan devBar ada dan punya struktur sama + return []; // atau sesuaikan jika ada devBar + case 1: + return navBar.map(section => section.id); + case 2: + return role1.map(section => section.id); + case 3: + return role2.map(section => section.id); + case 4: + return role3.map(section => section.id); + default: + return []; + } +} \ No newline at end of file diff --git a/src/app/api/[[...slugs]]/_lib/user/updt.ts b/src/app/api/[[...slugs]]/_lib/user/updt.ts index 5905d272..3b9a0d38 100644 --- a/src/app/api/[[...slugs]]/_lib/user/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/user/updt.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import { getMenuIdsByRoleId } from "@/app/admin/(dashboard)/user&role/_com/getMenuIdByRole"; import prisma from "@/lib/prisma"; import { Context } from "elysia"; @@ -33,6 +34,27 @@ export default async function userUpdate(context: Context) { const isRoleChanged = roleId && currentUser.roleId !== roleId; const isActiveChanged = isActive !== undefined && currentUser.isActive !== isActive; + // ✅ Jika role berubah, reset dan set ulang akses menu + if (isRoleChanged && roleId) { + // Hapus akses lama + await prisma.userMenuAccess.deleteMany({ + where: { userId: id } + }); + + // Ambil menu default untuk role baru + const menuIds = getMenuIdsByRoleId(roleId); + + if (menuIds.length > 0) { + // Buat akses baru + await prisma.userMenuAccess.createMany({ + data: menuIds.map(menuId => ({ + userId: id, + menuId + })) + }); + } + } + // Update user const updatedUser = await prisma.user.update({ where: { id }, From 54f83da3b89ee0d29b61d73cb7a08a20f48e8ea1 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 28 Nov 2025 15:35:21 +0800 Subject: [PATCH 2/6] fix ganti role, user menu access ikut ke create --- src/app/api/[[...slugs]]/_lib/user/updt.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/api/[[...slugs]]/_lib/user/updt.ts b/src/app/api/[[...slugs]]/_lib/user/updt.ts index b51923be..97bb8d96 100644 --- a/src/app/api/[[...slugs]]/_lib/user/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/user/updt.ts @@ -63,6 +63,8 @@ export default async function userUpdate(context: Context) { } } + + // Update user const updatedUser = await prisma.user.update({ where: { id }, From 1c1e8fb190fdbd7501953409b4f46f5d3e497720 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 28 Nov 2025 15:38:07 +0800 Subject: [PATCH 3/6] fix ganti role, user menu access ikut ke create fix --- src/app/api/[[...slugs]]/_lib/user/updt.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/app/api/[[...slugs]]/_lib/user/updt.ts b/src/app/api/[[...slugs]]/_lib/user/updt.ts index 97bb8d96..61e7ec59 100644 --- a/src/app/api/[[...slugs]]/_lib/user/updt.ts +++ b/src/app/api/[[...slugs]]/_lib/user/updt.ts @@ -35,13 +35,6 @@ export default async function userUpdate(context: Context) { const isActiveChanged = isActive !== undefined && currentUser.isActive !== isActive; - // ✅ Jika role berubah, hapus semua akses menu yang ada - if (isRoleChanged) { - await prisma.userMenuAccess.deleteMany({ - where: { userId: id } - }); - } - // ✅ Jika role berubah, reset dan set ulang akses menu if (isRoleChanged && roleId) { // Hapus akses lama @@ -63,8 +56,6 @@ export default async function userUpdate(context: Context) { } } - - // Update user const updatedUser = await prisma.user.update({ where: { id }, From 9bf3ec72cf76cf8bd7f0a6faf0ee7f9735fc7ba4 Mon Sep 17 00:00:00 2001 From: nico Date: Fri, 28 Nov 2025 17:04:35 +0800 Subject: [PATCH 4/6] Add --- src/app/layout.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index a12ceacd..ace97922 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -48,6 +48,7 @@ export default function RootLayout({ + Date: Fri, 28 Nov 2025 17:54:18 +0800 Subject: [PATCH 5/6] Test Google Insight --- src/app/globals.css | 80 ++++++++++++++++++++++++++++-- src/app/layout.tsx | 115 ++++++++++++++++++++++++++++++-------------- 2 files changed, 156 insertions(+), 39 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 5c98d487..775683b3 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,31 +1,105 @@ /* styles/globals.css */ + +/* =================================== + 1. IMPORT CSS LIBRARIES + =================================== */ +@import "@mantine/carousel/styles.css"; +@import "@mantine/dropzone/styles.css"; +@import "@mantine/charts/styles.css"; +@import "@mantine/dates/styles.css"; +@import "@mantine/tiptap/styles.css"; +@import "animate.css"; +@import "react-simple-toasts/dist/style.css"; +@import "react-simple-toasts/dist/theme/dark.css"; +@import "primereact/resources/themes/lara-light-blue/theme.css"; +@import "primereact/resources/primereact.min.css"; +@import "primeicons/primeicons.css"; + +/* =================================== + 2. FONT FACE - OPTIMIZED + =================================== */ @font-face { font-family: 'San Francisco'; src: url('/assets/fonts/font.otf') format('opentype'); font-weight: normal; font-style: normal; + font-display: swap; /* ✅ TAMBAHKAN INI - Penting untuk PageSpeed! */ } +/* =================================== + 3. RESET & BASE STYLES + =================================== */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + -webkit-text-size-adjust: 100%; /* Prevent font scaling in landscape */ + -moz-text-size-adjust: 100%; + text-size-adjust: 100%; +} + +body { + margin: 0; + font-family: 'San Francisco', -apple-system, BlinkMacSystemFont, 'Segoe UI', + Roboto, Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* =================================== + 4. GLASS EFFECTS - OPTIMIZED + =================================== */ .glass { background: rgba(255, 255, 255, 0.2); - -webkit-backdrop-filter: blur(40px); backdrop-filter: blur(40px); + -webkit-backdrop-filter: blur(40px); position: fixed; z-index: 50; width: 100%; height: 100vh; + will-change: transform; /* ✅ Hardware acceleration */ } .glass2 { background: rgba(255, 255, 255, 0.3); - -webkit-backdrop-filter: blur(40px); backdrop-filter: blur(40px); + -webkit-backdrop-filter: blur(40px); position: fixed; z-index: 1; + will-change: transform; /* ✅ Hardware acceleration */ } .glass3 { background: rgba(255, 255, 255, 0.3); - -webkit-backdrop-filter: blur(40px); backdrop-filter: blur(40px); + -webkit-backdrop-filter: blur(40px); + will-change: transform; /* ✅ Hardware acceleration */ } + +/* =================================== + 5. PERFORMANCE OPTIMIZATION + =================================== */ +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; + height: auto; +} + +/* Reduce motion for accessibility */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} \ No newline at end of file diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ace97922..764fb562 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,20 +1,5 @@ -// Import styles of packages that you've installed. -// All packages except `@mantine/hooks` require styles imports -import "@mantine/carousel/styles.css"; import "@mantine/core/styles.css"; -import '@mantine/dropzone/styles.css'; -import "animate.css"; -import 'react-simple-toasts/dist/style.css'; -import 'react-simple-toasts/dist/theme/dark.css'; -import "./globals.css"; -import '@mantine/charts/styles.css'; -import '@mantine/dates/styles.css'; -import '@mantine/tiptap/styles.css'; -import "primereact/resources/themes/lara-light-blue/theme.css"; -import "primereact/resources/primereact.min.css"; -import "primeicons/primeicons.css"; - - +import "./globals.css"; // Sisanya import di globals.css import LoadDataFirstClient from "@/app/darmasaba/_com/LoadDataFirstClient"; import { @@ -23,19 +8,82 @@ import { createTheme, mantineHtmlProps, } from "@mantine/core"; +import { Metadata } from "next"; import { ViewTransitions } from "next-view-transitions"; import { ToastContainer } from "react-toastify"; -export const metadata = { - title: "Desa Darmasaba", - description: "Desa Darmasaba Kabupaten Badung", +export const metadata: Metadata = { + title: { + default: "Desa Darmasaba", + template: "%s | Desa Darmasaba", + }, + description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", + keywords: [ + "desa darmasaba", + "darmasaba", + "badung", + "bali", + "desa", + "pemerintah desa", + "layanan publik", + "abang batan desa", + ], + authors: [{ name: "Pemerintah Desa Darmasaba" }], + creator: "Desa Darmasaba", + publisher: "Desa Darmasaba", + robots: { + index: true, + follow: true, + googleBot: { + index: true, + follow: true, + "max-video-preview": -1, + "max-image-preview": "large", + "max-snippet": -1, + }, + }, + icons: { + icon: "/assets/images/darmasaba-icon.png", + apple: "/assets/images/darmasaba-icon.png", + }, + manifest: "/manifest.json", + openGraph: { + type: "website", + locale: "id_ID", + url: "https://cld-dkr-staging-desa-darmasaba.wibudev.com", + siteName: "Desa Darmasaba", + title: "Desa Darmasaba - Kabupaten Badung, Bali", + description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", + images: [ + { + url: "/assets/images/darmasaba-icon.png", + width: 1200, + height: 630, + alt: "Desa Darmasaba", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: "Desa Darmasaba - Kabupaten Badung, Bali", + description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali", + images: ["/assets/images/darmasaba-icon.png"], + }, + verification: { + // google: "your-google-verification-code", // Tambahkan jika sudah punya + // yandex: "your-yandex-verification-code", + // yahoo: "your-yahoo-verification-code", + }, + category: "government", + other: { + "msapplication-TileColor": "#ffffff", + "theme-color": "#ffffff", + }, }; const theme = createTheme({ - fontFamily: - "San Francisco, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Arial, sans-serif", - fontFamilyMonospace: - "SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace", + fontFamily: "San Francisco, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif", + fontFamilyMonospace: "SFMono-Regular, Menlo, Monaco, Consolas, monospace", headings: { fontFamily: "San Francisco, sans-serif" }, }); @@ -46,27 +94,22 @@ export default function RootLayout({ }) { return ( - + - - {children} - + - + - ); -} +} \ No newline at end of file From 134ddc6154725fed6983353206cd2164b57b75e0 Mon Sep 17 00:00:00 2001 From: nico Date: Mon, 1 Dec 2025 10:21:00 +0800 Subject: [PATCH 6/6] Meta-data --- src/app/layout.tsx | 177 ++++++++++++++++++++++----------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 764fb562..0c68b72b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,80 +6,80 @@ import { ColorSchemeScript, MantineProvider, createTheme, - mantineHtmlProps, + // mantineHtmlProps, } from "@mantine/core"; -import { Metadata } from "next"; -import { ViewTransitions } from "next-view-transitions"; +// import { Metadata } from "next"; +// import { ViewTransitions } from "next-view-transitions"; import { ToastContainer } from "react-toastify"; -export const metadata: Metadata = { - title: { - default: "Desa Darmasaba", - template: "%s | Desa Darmasaba", - }, - description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", - keywords: [ - "desa darmasaba", - "darmasaba", - "badung", - "bali", - "desa", - "pemerintah desa", - "layanan publik", - "abang batan desa", - ], - authors: [{ name: "Pemerintah Desa Darmasaba" }], - creator: "Desa Darmasaba", - publisher: "Desa Darmasaba", - robots: { - index: true, - follow: true, - googleBot: { - index: true, - follow: true, - "max-video-preview": -1, - "max-image-preview": "large", - "max-snippet": -1, - }, - }, - icons: { - icon: "/assets/images/darmasaba-icon.png", - apple: "/assets/images/darmasaba-icon.png", - }, - manifest: "/manifest.json", - openGraph: { - type: "website", - locale: "id_ID", - url: "https://cld-dkr-staging-desa-darmasaba.wibudev.com", - siteName: "Desa Darmasaba", - title: "Desa Darmasaba - Kabupaten Badung, Bali", - description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", - images: [ - { - url: "/assets/images/darmasaba-icon.png", - width: 1200, - height: 630, - alt: "Desa Darmasaba", - }, - ], - }, - twitter: { - card: "summary_large_image", - title: "Desa Darmasaba - Kabupaten Badung, Bali", - description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali", - images: ["/assets/images/darmasaba-icon.png"], - }, - verification: { - // google: "your-google-verification-code", // Tambahkan jika sudah punya - // yandex: "your-yandex-verification-code", - // yahoo: "your-yahoo-verification-code", - }, - category: "government", - other: { - "msapplication-TileColor": "#ffffff", - "theme-color": "#ffffff", - }, -}; +// export const metadata: Metadata = { +// title: { +// default: "Desa Darmasaba", +// template: "%s | Desa Darmasaba", +// }, +// description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", +// keywords: [ +// "desa darmasaba", +// "darmasaba", +// "badung", +// "bali", +// "desa", +// "pemerintah desa", +// "layanan publik", +// "abang batan desa", +// ], +// authors: [{ name: "Pemerintah Desa Darmasaba" }], +// creator: "Desa Darmasaba", +// publisher: "Desa Darmasaba", +// robots: { +// index: true, +// follow: true, +// googleBot: { +// index: true, +// follow: true, +// "max-video-preview": -1, +// "max-image-preview": "large", +// "max-snippet": -1, +// }, +// }, +// icons: { +// icon: "/assets/images/darmasaba-icon.png", +// apple: "/assets/images/darmasaba-icon.png", +// }, +// manifest: "/manifest.json", +// openGraph: { +// type: "website", +// locale: "id_ID", +// url: "https://cld-dkr-staging-desa-darmasaba.wibudev.com", +// siteName: "Desa Darmasaba", +// title: "Desa Darmasaba - Kabupaten Badung, Bali", +// description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali. Informasi layanan publik, berita, dan profil desa.", +// images: [ +// { +// url: "/assets/images/darmasaba-icon.png", +// width: 1200, +// height: 630, +// alt: "Desa Darmasaba", +// }, +// ], +// }, +// twitter: { +// card: "summary_large_image", +// title: "Desa Darmasaba - Kabupaten Badung, Bali", +// description: "Website resmi Desa Darmasaba, Kabupaten Badung, Bali", +// images: ["/assets/images/darmasaba-icon.png"], +// }, +// verification: { +// // google: "your-google-verification-code", // Tambahkan jika sudah punya +// // yandex: "your-yandex-verification-code", +// // yahoo: "your-yahoo-verification-code", +// }, +// category: "government", +// other: { +// "msapplication-TileColor": "#ffffff", +// "theme-color": "#ffffff", +// }, +// }; const theme = createTheme({ fontFamily: "San Francisco, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif", @@ -93,23 +93,22 @@ export default function RootLayout({ children: React.ReactNode; }) { return ( - - - - - - - - {children} - - - - - - + + + + + + + + {children} + + + + + ); } \ No newline at end of file