Membuat database menu desa: Berita & Pengummuman
This commit is contained in:
91
src/app/admin/(dashboard)/_state/berita.ts
Normal file
91
src/app/admin/(dashboard)/_state/berita.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
judul: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
image: z.string().url().min(3, "Image minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
katagoryBeritaId: z.string().nonempty(),
|
||||
});
|
||||
|
||||
const category = proxy({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.KatagoryBeritaGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.berita.category["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
category.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
type BeritaForm = Prisma.BeritaGetPayload<{
|
||||
select: {
|
||||
judul: true;
|
||||
deskripsi: true;
|
||||
image: true;
|
||||
content: true;
|
||||
katagoryBeritaId: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const berita = proxy({
|
||||
create: {
|
||||
form: {} as BeritaForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
berita.create.form.image =
|
||||
"https://www.shutterstock.com/image-vector/lower-news-live-streaming-breaking-600nw-2535984111.jpg";
|
||||
const cek = templateForm.safeParse(berita.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
berita.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.berita["create"].post(
|
||||
berita.create.form
|
||||
);
|
||||
if (res.status === 200) {
|
||||
berita.findMany.load();
|
||||
return toast.success("succes create");
|
||||
}
|
||||
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
berita.create.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.BeritaGetPayload<{ omit: { isActive: true } }>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.berita["find-many"].get();
|
||||
console.log(res)
|
||||
if (res.status === 200) {
|
||||
berita.findMany.data = (res.data?.data as any) ?? [];
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const stateDashboardBerita = proxy({
|
||||
category,
|
||||
berita,
|
||||
});
|
||||
|
||||
export default stateDashboardBerita;
|
||||
83
src/app/admin/(dashboard)/_state/pengumuman.ts
Normal file
83
src/app/admin/(dashboard)/_state/pengumuman.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import ApiFetch from "@/lib/api-fetch"
|
||||
import { Prisma } from "@prisma/client"
|
||||
import { toast } from "react-toastify"
|
||||
import { proxy } from "valtio"
|
||||
import { z } from "zod"
|
||||
|
||||
const templateFormPengumuman = z.object({
|
||||
judul: z.string().min(3, "Judul minimal 3 karakter"),
|
||||
deskripsi: z.string().min(3, "Deskripsi minimal 3 karakter"),
|
||||
content: z.string().min(3, "Content minimal 3 karakter"),
|
||||
categoryPengumumanId: z.string().nonempty(),
|
||||
})
|
||||
|
||||
const category = proxy ({
|
||||
findMany: {
|
||||
data: null as
|
||||
| null
|
||||
| Prisma.CategoryPengumumanGetPayload<{ omit: { isActive: true } }>[],
|
||||
async load() {
|
||||
const res = await ApiFetch.api.desa.pengumuman.category["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
category.findMany.data = res.data?.data as any ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
type PengumumanForm = Prisma.PengumumanGetPayload<{
|
||||
select: {
|
||||
judul: true;
|
||||
deskripsi: true;
|
||||
content: true;
|
||||
categoryPengumumanId: true;
|
||||
}
|
||||
}>
|
||||
const pengumuman = proxy({
|
||||
create: {
|
||||
form: {} as PengumumanForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateFormPengumuman.safeParse(pengumuman.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
pengumuman.create.loading = true;
|
||||
const res = await ApiFetch.api.desa.pengumuman["create"].post(pengumuman.create.form)
|
||||
if (res.status === 200) {
|
||||
pengumuman.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
console.log(res)
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally{
|
||||
pengumuman.create.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.PengumumanGetPayload<{omit: {isActive: true}}>[]
|
||||
| null,
|
||||
async load () {
|
||||
const res = await ApiFetch.api.desa.pengumuman["find-many"].get();
|
||||
console.log(res)
|
||||
if (res.status === 200) {
|
||||
pengumuman.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const stateDesaPengumuman = proxy({
|
||||
category,
|
||||
pengumuman
|
||||
})
|
||||
export default stateDesaPengumuman
|
||||
85
src/app/admin/(dashboard)/desa/berita/_com/BeritaEditor.tsx
Normal file
85
src/app/admin/(dashboard)/desa/berita/_com/BeritaEditor.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
'use client'
|
||||
import { RichTextEditor, Link } from '@mantine/tiptap';
|
||||
import { useEditor } from '@tiptap/react';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import TextAlign from '@tiptap/extension-text-align';
|
||||
import Superscript from '@tiptap/extension-superscript';
|
||||
import SubScript from '@tiptap/extension-subscript';
|
||||
import { Button, Stack } from '@mantine/core';
|
||||
|
||||
const content =
|
||||
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup><sup /></sup> and <sub><sub /></sub> tags)</li><li>Ordered and bullet lists</li><li>Text align </li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
|
||||
|
||||
export function BeritaEditor({ onSubmit }: { onSubmit: (val: string) => void }) {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Link,
|
||||
Superscript,
|
||||
SubScript,
|
||||
Highlight,
|
||||
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
||||
],
|
||||
content,
|
||||
});
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<RichTextEditor editor={editor}>
|
||||
<RichTextEditor.Toolbar sticky stickyOffset={60}>
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Bold />
|
||||
<RichTextEditor.Italic />
|
||||
<RichTextEditor.Underline />
|
||||
<RichTextEditor.Strikethrough />
|
||||
<RichTextEditor.ClearFormatting />
|
||||
<RichTextEditor.Highlight />
|
||||
<RichTextEditor.Code />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.H1 />
|
||||
<RichTextEditor.H2 />
|
||||
<RichTextEditor.H3 />
|
||||
<RichTextEditor.H4 />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Blockquote />
|
||||
<RichTextEditor.Hr />
|
||||
<RichTextEditor.BulletList />
|
||||
<RichTextEditor.OrderedList />
|
||||
<RichTextEditor.Subscript />
|
||||
<RichTextEditor.Superscript />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Link />
|
||||
<RichTextEditor.Unlink />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.AlignLeft />
|
||||
<RichTextEditor.AlignCenter />
|
||||
<RichTextEditor.AlignJustify />
|
||||
<RichTextEditor.AlignRight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Undo />
|
||||
<RichTextEditor.Redo />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
</RichTextEditor.Toolbar>
|
||||
|
||||
<RichTextEditor.Content />
|
||||
</RichTextEditor>
|
||||
<Button onClick={() => {
|
||||
if (!editor) return
|
||||
onSubmit(editor?.getHTML())
|
||||
}}>Submit</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,88 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import { Center, Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { IconImageInPicture } from '@tabler/icons-react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateDashboardBerita from '../../_state/berita';
|
||||
import { BeritaEditor } from './_com/BeritaEditor';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
Berita
|
||||
</div>
|
||||
<Stack>
|
||||
<SimpleGrid cols={2}>
|
||||
<BeritaList />
|
||||
<BeritaCreate />
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function BeritaList() {
|
||||
const beritaState = useProxy(stateDashboardBerita)
|
||||
useShallowEffect(() => {
|
||||
beritaState.berita.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!beritaState.berita.findMany.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
return <Stack>
|
||||
<Text>News List</Text>
|
||||
{beritaState.berita.findMany.data?.map((item) => (
|
||||
<Text key={item.id}>{item.judul}</Text>
|
||||
))}
|
||||
</Stack>
|
||||
}
|
||||
|
||||
function BeritaCreate() {
|
||||
const beritaState = useProxy(stateDashboardBerita)
|
||||
return <Stack gap={"md"}>
|
||||
<Text>Create Some News</Text>
|
||||
<SelectCategory onChange={(val) => {
|
||||
beritaState.berita.create.form.katagoryBeritaId = val.id
|
||||
}} />
|
||||
<TextInput onChange={(val) => {
|
||||
beritaState.berita.create.form.judul = val.target.value
|
||||
}} label={"Judul"} placeholder='masukkan judul' />
|
||||
<TextInput onChange={(val) => {
|
||||
beritaState.berita.create.form.deskripsi = val.target.value
|
||||
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
|
||||
<Center w={200} h={200} bg={"gray"}>
|
||||
<IconImageInPicture />
|
||||
</Center>
|
||||
<BeritaEditor onSubmit={(val) => {
|
||||
|
||||
beritaState.berita.create.form.content = val
|
||||
beritaState.berita.create.create()
|
||||
}} />
|
||||
</Stack>
|
||||
}
|
||||
|
||||
function SelectCategory({ onChange }: {
|
||||
onChange: (value: Prisma.KatagoryBeritaGetPayload<{
|
||||
select: {
|
||||
name: true,
|
||||
id: true
|
||||
}
|
||||
}>) => void
|
||||
}) {
|
||||
const beritaState = useProxy(stateDashboardBerita)
|
||||
useShallowEffect(() => {
|
||||
beritaState.category.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!beritaState.category.findMany.data) return <Skeleton h={40} />
|
||||
return <Group>
|
||||
<Select placeholder='pilih katagori' label={"select katagori"} data={beritaState.category.findMany.data.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))} onChange={(v) => {
|
||||
const data = beritaState.category.findMany.data?.find((item) => item.id === v)
|
||||
if (!data) return
|
||||
onChange(data)
|
||||
}} />
|
||||
</Group>
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -1,11 +1,89 @@
|
||||
'use client'
|
||||
import { Group, Select, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateDesaPengumuman from '../../_state/pengumuman';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { BeritaEditor } from '../berita/_com/BeritaEditor';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
Pengumuman
|
||||
</div>
|
||||
<Stack>
|
||||
<SimpleGrid cols={{
|
||||
base: 1, md: 2
|
||||
}}>
|
||||
<PengumumanList />
|
||||
<PengumumanCreate />
|
||||
</SimpleGrid>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function PengumumanList() {
|
||||
const pengumumanState = useProxy(stateDesaPengumuman)
|
||||
useShallowEffect(() => {
|
||||
pengumumanState.pengumuman.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!pengumumanState.pengumuman.findMany.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
return <Stack>
|
||||
<Text>Announcement List</Text>
|
||||
{pengumumanState.pengumuman.findMany.data?.map((item) => (
|
||||
<Text key={item.id}>{item.judul}</Text>
|
||||
))}
|
||||
</Stack>;
|
||||
}
|
||||
|
||||
function PengumumanCreate() {
|
||||
const pengumumanState = useProxy(stateDesaPengumuman)
|
||||
|
||||
|
||||
return <Stack gap={"md"}>
|
||||
<Text>Create Some Announcement</Text>
|
||||
<SelectCategory onChange={(val) => {
|
||||
pengumumanState.pengumuman.create.form.categoryPengumumanId = val.id
|
||||
}} />
|
||||
<TextInput onChange={(val) => {
|
||||
pengumumanState.pengumuman.create.form.judul = val.target.value
|
||||
}} label={"Judul"} placeholder='masukkan judul' />
|
||||
<TextInput onChange={(val) => {
|
||||
pengumumanState.pengumuman.create.form.deskripsi = val.target.value
|
||||
}} label={"Deskripsi"} placeholder='masukkan deskripsi' />
|
||||
<BeritaEditor onSubmit={(val) => {
|
||||
pengumumanState.pengumuman.create.form.content = val
|
||||
pengumumanState.pengumuman.create.create()
|
||||
}} />
|
||||
</Stack>
|
||||
}
|
||||
|
||||
function SelectCategory({ onChange }: {
|
||||
onChange: (value: Prisma.CategoryPengumumanGetPayload<{
|
||||
select: {
|
||||
name: true,
|
||||
id: true
|
||||
}
|
||||
}>) => void
|
||||
}) {
|
||||
const pengumumanState = useProxy(stateDesaPengumuman)
|
||||
useShallowEffect(() => {
|
||||
pengumumanState.category.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!pengumumanState.category.findMany.data) return <Skeleton h={40} />
|
||||
return <Group>
|
||||
{/* {JSON.stringify(pengumumanState.category.findMany.data)} */}
|
||||
<Select placeholder='pilih kategori' label={"select katagori"} data={pengumumanState.category.findMany.data.map((item) => ({
|
||||
value: item.id,
|
||||
label: item.name
|
||||
}))} onChange={(v) => {
|
||||
const data = pengumumanState.category.findMany.data?.find((item) => item.id === v)
|
||||
if (!data) return
|
||||
onChange(data)
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
}
|
||||
export default Page;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Text } from '@mantine/core';
|
||||
|
||||
function CompTextLengh({input, maxLength}: {input: string, maxLength: number}) {
|
||||
return (
|
||||
<div>
|
||||
<Text fz={"xs"}>{input.length}/{maxLength}</Text>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CompTextLengh;
|
||||
@@ -1 +0,0 @@
|
||||
export const maxLength = 2000
|
||||
@@ -1,13 +1,8 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Stack, Text, Textarea, Title } from '@mantine/core';
|
||||
import { useState } from 'react';
|
||||
import CompTextLengh from './_comp_textLengh';
|
||||
import { maxLength } from './gs_maxLength';
|
||||
|
||||
function Page(
|
||||
) {
|
||||
const [value, setValue] = useState("")
|
||||
function Page() {
|
||||
return (
|
||||
<Box>
|
||||
<Stack gap={"xs"}>
|
||||
@@ -15,13 +10,10 @@ function Page(
|
||||
<Textarea
|
||||
label={<Text>Deskripsi</Text>}
|
||||
placeholder='tambah deskripsi'
|
||||
maxLength={maxLength}
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
/>
|
||||
<CompTextLengh input={value} maxLength={maxLength}/>
|
||||
<Group>
|
||||
<Button bg={colors['blue-button']} fz={'md'}>Submit</Button>
|
||||
<Button
|
||||
bg={colors['blue-button']} fz={'md'}>Submit</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
@@ -1,67 +1,87 @@
|
||||
'use client'
|
||||
import colors from "@/con/colors";
|
||||
import { ActionIcon, AppShell, AppShellHeader, AppShellMain, AppShellNavbar, Burger, Group, Image, NavLink, ScrollArea, Stack, Text } from "@mantine/core";
|
||||
import { ActionIcon, AppShell, AppShellHeader, AppShellMain, AppShellNavbar, Burger, Group, Image, NavLink, ScrollArea, Text } from "@mantine/core";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { IconChevronLeft, IconChevronRight } from "@tabler/icons-react";
|
||||
import _ from 'lodash';
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
import { useSelectedLayoutSegments } from "next/navigation";
|
||||
import { navBar } from "./_com/list_PageAdmin";
|
||||
|
||||
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
const [opened, { toggle }] = useDisclosure();
|
||||
const [active, setActive] = useState(navBar[0]?.id || 0);
|
||||
const isClient = typeof window !== 'undefined';
|
||||
const [desktopOpened, { toggle: toggleDesktop }] =
|
||||
useDisclosure(true);
|
||||
|
||||
|
||||
const segments = useSelectedLayoutSegments()
|
||||
return (
|
||||
<Stack h={"100%"}>
|
||||
<AppShell
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 300, breakpoint: 'sm', collapsed: { mobile: !opened }
|
||||
}}
|
||||
padding={'md'}
|
||||
>
|
||||
<AppShellHeader bg={colors["white-trans-1"]}>
|
||||
<Group px={10} align="center">
|
||||
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size={'sm'} />
|
||||
<ActionIcon w={50} h={50} variant="transparent" component={Link} href="/admin">
|
||||
<AppShell
|
||||
suppressHydrationWarning
|
||||
header={{ height: 60 }}
|
||||
navbar={{
|
||||
width: 300, breakpoint: 'sm', collapsed: { mobile: !opened, desktop: !desktopOpened }
|
||||
}}
|
||||
padding={'md'}
|
||||
>
|
||||
<AppShellHeader bg={colors["white-trans-1"]}>
|
||||
<Group px={10} align="center">
|
||||
{!desktopOpened && <ActionIcon variant="light" onClick={toggleDesktop}><IconChevronRight /></ActionIcon>}
|
||||
<Burger opened={opened} onClick={toggle} hiddenFrom="sm" size={'sm'} />
|
||||
<ActionIcon w={50} h={50} variant="transparent" component={Link} href="/admin">
|
||||
<Image py={5} src={'/assets/images/darmasaba-icon.png'} alt="" width={50} height={50} />
|
||||
</ActionIcon>
|
||||
<Text fw={'bold'} c={colors["blue-button"]} fz={'lg'}>Dashboard Admin</Text>
|
||||
</Group>
|
||||
</AppShellHeader>
|
||||
<AppShellNavbar
|
||||
c={colors["blue-button"]}
|
||||
component={ScrollArea}
|
||||
>
|
||||
{navBar.map((v,k) => {
|
||||
</ActionIcon>
|
||||
<Text fw={'bold'} c={colors["blue-button"]} fz={'lg'}>Dashboard Admin</Text>
|
||||
</Group>
|
||||
</AppShellHeader>
|
||||
<AppShellNavbar
|
||||
|
||||
c={colors["blue-button"]}
|
||||
component={ScrollArea}
|
||||
>
|
||||
<AppShell.Section h={100} bg={"gray.1"}>
|
||||
<Text c={colors["blue-button"]}>Heder Navbar</Text>
|
||||
</AppShell.Section>
|
||||
<AppShell.Section >
|
||||
{navBar.map((v, k) => {
|
||||
return (
|
||||
<NavLink
|
||||
c={colors["blue-button"]}
|
||||
c={_.lowerCase(v.name) == segments[1] ? colors["blue-button"] : "grey"}
|
||||
key={k}
|
||||
active={isClient && k === active}
|
||||
onClick={() => setActive(k)}
|
||||
label={<Text>{v.name}</Text>}
|
||||
defaultOpened={_.lowerCase(v.name) == segments[1]}
|
||||
// onClick={() => setActive(k)}
|
||||
label={<Text
|
||||
style={{ fontWeight: _.lowerCase(v.name) == segments[1] ? "bold" : "normal" }}
|
||||
>{v.name}</Text>}
|
||||
>
|
||||
{v.children.map((child) => {
|
||||
{v.children.map((child, key) => {
|
||||
return (
|
||||
<NavLink
|
||||
c={_.lowerCase(child.name) == _.lowerCase(segments[2]) ? colors["blue-button"] : "grey"}
|
||||
key={key}
|
||||
href={child.path}
|
||||
key={child.id}
|
||||
active={isClient && Number(child.id) === active}
|
||||
onClick={() => setActive(Number(child.id))}
|
||||
label={<Text>{child.name}</Text>}
|
||||
// active={isClient && Number(child.id) === active}
|
||||
// onClick={() => setActive(Number(child.id))}
|
||||
label={<Text
|
||||
style={{ fontWeight: _.lowerCase(child.name) == _.lowerCase(segments[2]) ? "bold" : "normal" }}
|
||||
>{child.name}</Text>}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</NavLink>
|
||||
)
|
||||
})}
|
||||
</AppShellNavbar>
|
||||
<AppShellMain bg={colors.Bg}>
|
||||
{children}
|
||||
</AppShellMain>
|
||||
</AppShell>
|
||||
</Stack>
|
||||
</AppShell.Section>
|
||||
|
||||
<AppShell.Section>
|
||||
<Group justify="end">
|
||||
<ActionIcon variant="light" onClick={toggleDesktop}><IconChevronLeft /></ActionIcon>
|
||||
</Group>
|
||||
</AppShell.Section>
|
||||
</AppShellNavbar>
|
||||
<AppShellMain bg={colors.Bg}>
|
||||
{children}
|
||||
</AppShellMain>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user