Compare commits

...

8 Commits

4 changed files with 211 additions and 54 deletions

View File

@@ -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 [];
}
}

View File

@@ -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";
@@ -34,11 +35,25 @@ 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) {
// ✅ 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

View File

@@ -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;
}
}

View File

@@ -1,41 +1,89 @@
// 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 {
ColorSchemeScript,
MantineProvider,
createTheme,
mantineHtmlProps,
// mantineHtmlProps,
} from "@mantine/core";
import { ViewTransitions } from "next-view-transitions";
// 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" },
});
@@ -45,27 +93,22 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<ViewTransitions>
<html lang="en" {...mantineHtmlProps}>
<head>
<ColorSchemeScript />
<link
rel="icon"
href="/assets/images/darmasaba-icon.png"
sizes="any"
/>
</head>
<body>
<MantineProvider theme={theme}>
{children}
</MantineProvider>
<ToastContainer position="bottom-center" hideProgressBar style={{
zIndex: 9999
}} />
</body>
<LoadDataFirstClient />
</html>
</ViewTransitions>
<html lang="id" data-mantine-color-scheme="light">
<head>
<meta charSet="utf-8" />
<ColorSchemeScript />
</head>
<body>
<MantineProvider theme={theme}>
{children}
<LoadDataFirstClient />
</MantineProvider>
<ToastContainer
position="bottom-center"
hideProgressBar
style={{ zIndex: 9999 }}
/>
</body>
</html>
);
}
}