From 1e7acac193a45bed7bceb84c9c2e5de39892a1f4 Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 25 Feb 2026 21:18:26 +0800 Subject: [PATCH 1/3] Fix eror build --- .../_seeder_list/desa/berita/seed_berita.ts | 61 +++++++++++++------ .../desa/profil/profil-perbekel/page.tsx | 2 +- src/app/admin/layout.tsx | 6 +- .../_lib/desa/berita/kategori-berita/del.ts | 1 - .../_lib/desa/potensi/find-unique.ts | 3 +- .../_lib/desa/potensi/kategori-potensi/del.ts | 1 - .../profile_desa/sejarah/find-first.ts | 8 +-- .../profile/profile_desa/sejarah/index.ts | 4 +- .../profile/profile_desa/sejarah/update.ts | 2 +- src/components/admin/UnifiedSurface.tsx | 9 ++- src/components/admin/UnifiedTypography.tsx | 36 +++++++++-- src/lib/api-auth.ts | 31 +++++----- src/utils/themeTokens.ts | 4 ++ 13 files changed, 110 insertions(+), 58 deletions(-) diff --git a/prisma/_seeder_list/desa/berita/seed_berita.ts b/prisma/_seeder_list/desa/berita/seed_berita.ts index 1d1fb9f0..53b9d41b 100644 --- a/prisma/_seeder_list/desa/berita/seed_berita.ts +++ b/prisma/_seeder_list/desa/berita/seed_berita.ts @@ -26,7 +26,24 @@ export async function seedBerita() { console.log("🔄 Seeding Berita..."); + // Build a map of valid kategori IDs + const validKategoriIds = new Set(); + const kategoriList = await prisma.kategoriBerita.findMany({ + select: { id: true, name: true }, + }); + kategoriList.forEach((k) => validKategoriIds.add(k.id)); + + console.log(`📋 Found ${validKategoriIds.size} valid kategori IDs in database`); + for (const b of beritaJson) { + // Validate kategoriBeritaId exists + if (!b.kategoriBeritaId || !validKategoriIds.has(b.kategoriBeritaId)) { + console.warn( + `⚠️ Skipping berita "${b.judul}": Invalid kategoriBeritaId "${b.kategoriBeritaId}"`, + ); + continue; + } + let imageId: string | null = null; if (b.imageName) { @@ -44,26 +61,32 @@ export async function seedBerita() { } } - await prisma.berita.upsert({ - where: { id: b.id }, - update: { - judul: b.judul, - deskripsi: b.deskripsi, - content: b.content, - kategoriBeritaId: b.kategoriBeritaId, - imageId, - }, - create: { - id: b.id, - judul: b.judul, - deskripsi: b.deskripsi, - content: b.content, - kategoriBeritaId: b.kategoriBeritaId, - imageId, - }, - }); + try { + await prisma.berita.upsert({ + where: { id: b.id }, + update: { + judul: b.judul, + deskripsi: b.deskripsi, + content: b.content, + kategoriBeritaId: b.kategoriBeritaId, + imageId, + }, + create: { + id: b.id, + judul: b.judul, + deskripsi: b.deskripsi, + content: b.content, + kategoriBeritaId: b.kategoriBeritaId, + imageId, + }, + }); - console.log(`✅ Berita seeded: ${b.judul}`); + console.log(`✅ Berita seeded: ${b.judul}`); + } catch (error: any) { + console.error( + `❌ Failed to seed berita "${b.judul}": ${error.message}`, + ); + } } console.log("🎉 Berita seed selesai"); diff --git a/src/app/admin/(dashboard)/desa/profil/profil-perbekel/page.tsx b/src/app/admin/(dashboard)/desa/profil/profil-perbekel/page.tsx index e79103d6..d3b1cb21 100644 --- a/src/app/admin/(dashboard)/desa/profil/profil-perbekel/page.tsx +++ b/src/app/admin/(dashboard)/desa/profil/profil-perbekel/page.tsx @@ -95,7 +95,7 @@ function Page() { fz={{ base: 'md', md: 'lg' }} lh={{ base: 1.4, md: 1.4 }} > - {perbekel.nama || "I.B. Surya Prabhawa Manuaba, S.H., M.H."} + I.B. Surya Prabhawa Manuaba, S.H., M.H. diff --git a/src/app/admin/layout.tsx b/src/app/admin/layout.tsx index b38ac3f5..edf8a02c 100644 --- a/src/app/admin/layout.tsx +++ b/src/app/admin/layout.tsx @@ -1,9 +1,9 @@ 'use client' -import { authStore } from "@/store/authStore"; -import { useDarkMode } from "@/state/darkModeStore"; -import { themeTokens, getActiveStateStyles } from "@/utils/themeTokens"; import { DarkModeToggle } from "@/components/admin/DarkModeToggle"; +import { useDarkMode } from "@/state/darkModeStore"; +import { authStore } from "@/store/authStore"; +import { themeTokens } from "@/utils/themeTokens"; import { ActionIcon, AppShell, diff --git a/src/app/api/[[...slugs]]/_lib/desa/berita/kategori-berita/del.ts b/src/app/api/[[...slugs]]/_lib/desa/berita/kategori-berita/del.ts index 7e24bc8e..376e4a3d 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/berita/kategori-berita/del.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/berita/kategori-berita/del.ts @@ -17,7 +17,6 @@ export default async function kategoriBeritaDelete(context: Context) { where: { kategoriBeritaId: id, isActive: true, - deletedAt: null, }, }); diff --git a/src/app/api/[[...slugs]]/_lib/desa/potensi/find-unique.ts b/src/app/api/[[...slugs]]/_lib/desa/potensi/find-unique.ts index dc431265..48365f42 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/potensi/find-unique.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/potensi/find-unique.ts @@ -23,10 +23,9 @@ export default async function findUnique( // ✅ Filter by isActive and deletedAt const data = await prisma.potensiDesa.findFirst({ - where: { + where: { id, isActive: true, - deletedAt: null, }, include: { image: true, diff --git a/src/app/api/[[...slugs]]/_lib/desa/potensi/kategori-potensi/del.ts b/src/app/api/[[...slugs]]/_lib/desa/potensi/kategori-potensi/del.ts index 356d73f0..5dd4bbe5 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/potensi/kategori-potensi/del.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/potensi/kategori-potensi/del.ts @@ -17,7 +17,6 @@ export default async function kategoriPotensiDelete(context: Context) { where: { kategoriId: id, isActive: true, - deletedAt: null, }, }); diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-first.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-first.ts index c5b8359b..9ad4cefb 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-first.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/find-first.ts @@ -1,10 +1,9 @@ import prisma from "@/lib/prisma"; import { requireAuth } from "@/lib/api-auth"; -export default async function sejarahDesaFindFirst(request: Request) { +export default async function sejarahDesaFindFirst() { // ✅ Authentication check - const headers = new Headers(request.url); - const authResult = await requireAuth({ headers }); + const authResult = await requireAuth(); if (!authResult.authenticated) { return authResult.response; } @@ -12,9 +11,8 @@ export default async function sejarahDesaFindFirst(request: Request) { try { // Get the first active record const data = await prisma.sejarahDesa.findFirst({ - where: { + where: { isActive: true, - deletedAt: null }, orderBy: { createdAt: 'asc' } // Get the oldest one first }); diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts index 5f39e890..74511381 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/index.ts @@ -7,8 +7,8 @@ const SejarahDesa = new Elysia({ prefix: "/sejarah", tags: ["Desa/Profile"], }) - .get("/first", async (context) => { - const response = await sejarahDesaFindFirst(new Request(context.request)); + .get("/first", async () => { + const response = await sejarahDesaFindFirst(); return response; }) .get("/:id", async (context) => { diff --git a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts index aeedfde5..50997887 100644 --- a/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts +++ b/src/app/api/[[...slugs]]/_lib/desa/profile/profile_desa/sejarah/update.ts @@ -4,7 +4,7 @@ import { Context } from "elysia"; export default async function sejarahDesaUpdate(context: Context) { // ✅ Authentication check - const authResult = await requireAuth(context); + const authResult = await requireAuth(); if (!authResult.authenticated) { return authResult.response; } diff --git a/src/components/admin/UnifiedSurface.tsx b/src/components/admin/UnifiedSurface.tsx index c00f911b..1ebd47fc 100644 --- a/src/components/admin/UnifiedSurface.tsx +++ b/src/components/admin/UnifiedSurface.tsx @@ -2,7 +2,7 @@ import { useDarkMode } from '@/state/darkModeStore'; import { themeTokens } from '@/utils/themeTokens'; -import { Paper, Box, BoxProps, Divider, DividerProps } from '@mantine/core'; +import { Box, BoxProps, Divider, DividerProps, Paper } from '@mantine/core'; import React from 'react'; /** @@ -22,7 +22,6 @@ import React from 'react'; // ============================================================================ // Unified Card Component - * ============================================================================ interface UnifiedCardProps extends BoxProps { withBorder?: boolean; @@ -63,12 +62,18 @@ export function UnifiedCard({ } }; + const getShadow = () => { + if (shadow === 'none') return 'none'; + return tokens.shadows[shadow]; + }; + return ( { if (color === 'primary') return tokens.colors.text.primary; if (color === 'secondary') return tokens.colors.text.secondary; - if (color === 'brand') return tokens.colors.brand; + if (color === 'brand') return tokens.colors.text.brand; return color; }; @@ -109,8 +111,14 @@ interface UnifiedTextProps { align?: 'left' | 'center' | 'right'; color?: 'primary' | 'secondary' | 'tertiary' | 'muted' | 'brand' | 'link' | string; lineClamp?: number; - truncate?: 'start' | 'end' | 'middle' | boolean; + truncate?: TextTruncate; span?: boolean; + mt?: string; + mb?: string; + ml?: string; + mr?: string; + mx?: string; + my?: string; style?: React.CSSProperties; } @@ -123,6 +131,12 @@ export function UnifiedText({ lineClamp, truncate, span = false, + mt, + mb, + ml, + mr, + mx, + my, style, }: UnifiedTextProps) { const { isDark } = useDarkMode(); @@ -163,7 +177,7 @@ export function UnifiedText({ case 'muted': return tokens.colors.text.muted; case 'brand': - return tokens.colors.brand; + return tokens.colors.text.brand; case 'link': return tokens.colors.text.link; default: @@ -177,7 +191,7 @@ export function UnifiedText({ if (span) { return ( - {children} - + ); } @@ -201,6 +221,12 @@ export function UnifiedText({ c={textColor} lineClamp={lineClamp} truncate={truncate} + mt={mt} + mb={mb} + ml={ml} + mr={mr} + mx={mx} + my={my} style={style} > {children} diff --git a/src/lib/api-auth.ts b/src/lib/api-auth.ts index d639b296..a566f569 100644 --- a/src/lib/api-auth.ts +++ b/src/lib/api-auth.ts @@ -1,11 +1,11 @@ /** * Authentication helper untuk API endpoints - * + * * Usage: * import { requireAuth } from "@/lib/api-auth"; - * - * export default async function myEndpoint(context: Context) { - * const authResult = await requireAuth(context); + * + * export default async function myEndpoint() { + * const authResult = await requireAuth(); * if (!authResult.authenticated) { * return authResult.response; * } @@ -13,24 +13,24 @@ * } */ -import { getSession } from "@/lib/session"; +import { getSession, SessionData } from "@/lib/session"; -export type AuthResult = - | { authenticated: true; user: any } +export type AuthResult = + | { authenticated: true; user: NonNullable } | { authenticated: false; response: Response }; -export async function requireAuth(context: any): Promise { +export async function requireAuth(): Promise { try { // Cek session dari cookies const session = await getSession(); - + if (!session || !session.user) { return { authenticated: false, response: new Response(JSON.stringify({ success: false, message: "Unauthorized - Silakan login terlebih dahulu" - }), { + }), { status: 401, headers: { 'Content-Type': 'application/json' } }) @@ -44,7 +44,7 @@ export async function requireAuth(context: any): Promise { response: new Response(JSON.stringify({ success: false, message: "Akun Anda tidak aktif. Hubungi administrator." - }), { + }), { status: 403, headers: { 'Content-Type': 'application/json' } }) @@ -55,14 +55,13 @@ export async function requireAuth(context: any): Promise { authenticated: true, user: session.user }; - } catch (error) { - console.error("Auth error:", error); + } catch { return { authenticated: false, response: new Response(JSON.stringify({ success: false, message: "Authentication error" - }), { + }), { status: 500, headers: { 'Content-Type': 'application/json' } }) @@ -74,11 +73,11 @@ export async function requireAuth(context: any): Promise { * Optional auth - tidak error jika tidak authenticated * Berguna untuk endpoint yang bisa diakses public atau private */ -export async function optionalAuth(context: any): Promise { +export async function optionalAuth(): Promise | null> { try { const session = await getSession(); return session?.user || null; - } catch (error) { + } catch { return null; } } diff --git a/src/utils/themeTokens.ts b/src/utils/themeTokens.ts index 75c133a0..c0efc1a8 100644 --- a/src/utils/themeTokens.ts +++ b/src/utils/themeTokens.ts @@ -223,6 +223,10 @@ export const themeTokens = (isDark: boolean = false): ThemeTokens => { hoverSoft: 'rgba(25, 113, 194, 0.03)', hoverMedium: 'rgba(25, 113, 194, 0.05)', activeAccent: 'rgba(25, 113, 194, 0.1)', + success: '#22c55e', + warning: '#facc15', + error: '#ef4444', + info: '#38bdf8', }; const current = isDark ? darkColors : lightColors; -- 2.49.1 From 8e8c133eeafb125ab12fb16f41d6a209c877060c Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 25 Feb 2026 21:19:56 +0800 Subject: [PATCH 2/3] Fix eror build --- src/utils/themeTokens.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/themeTokens.ts b/src/utils/themeTokens.ts index c0efc1a8..f8413c22 100644 --- a/src/utils/themeTokens.ts +++ b/src/utils/themeTokens.ts @@ -385,3 +385,4 @@ export const getActiveStateStyles = (isActive: boolean, isDark: boolean = false) }, }; }; + -- 2.49.1 From f1729151b34502f68e9e42790e9bb5c79280fd06 Mon Sep 17 00:00:00 2001 From: nico Date: Wed, 25 Feb 2026 21:24:39 +0800 Subject: [PATCH 3/3] Fix themeTokens light mode status colors Co-authored-by: Qwen-Coder --- src/utils/themeTokens.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/themeTokens.ts b/src/utils/themeTokens.ts index f8413c22..7de99f30 100644 --- a/src/utils/themeTokens.ts +++ b/src/utils/themeTokens.ts @@ -386,3 +386,6 @@ export const getActiveStateStyles = (isActive: boolean, isDark: boolean = false) }; }; + + + -- 2.49.1