tambahan untuk divisi
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const nextConfig = {};
|
const nextConfig = {
|
||||||
|
devIndicators: {
|
||||||
|
buildActivityPosition: 'bottom-right',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
"seed": "tsx prisma/seed.ts"
|
"seed": "tsx prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hookstate/core": "^4.0.1",
|
||||||
|
"@hookstate/localstored": "^4.0.2",
|
||||||
"@mantine/carousel": "^7.11.1",
|
"@mantine/carousel": "^7.11.1",
|
||||||
"@mantine/charts": "^7.11.0",
|
"@mantine/charts": "^7.11.0",
|
||||||
"@mantine/code-highlight": "^7.11.0",
|
"@mantine/code-highlight": "^7.11.0",
|
||||||
@@ -30,13 +32,16 @@
|
|||||||
"@tiptap/extension-link": "^2.4.0",
|
"@tiptap/extension-link": "^2.4.0",
|
||||||
"@tiptap/react": "^2.4.0",
|
"@tiptap/react": "^2.4.0",
|
||||||
"@tiptap/starter-kit": "^2.4.0",
|
"@tiptap/starter-kit": "^2.4.0",
|
||||||
|
"@types/lodash": "^4.17.6",
|
||||||
"dayjs": "^1.11.11",
|
"dayjs": "^1.11.11",
|
||||||
"embla-carousel-autoplay": "^7.1.0",
|
"embla-carousel-autoplay": "^7.1.0",
|
||||||
"embla-carousel-react": "^7.1.0",
|
"embla-carousel-react": "^7.1.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
"next": "14.2.4",
|
"next": "14.2.4",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-icons": "^5.2.1",
|
"react-icons": "^5.2.1",
|
||||||
|
"react-simple-toasts": "^5.10.0",
|
||||||
"recharts": "2"
|
"recharts": "2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { DevisionLayout } from "@/module/division/ui/DevisionLayout";
|
import { DevisionLayout } from "@/module/division/ui/DivisionLayout";
|
||||||
|
|
||||||
|
|
||||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||||
return <DevisionLayout>
|
return <DevisionLayout>
|
||||||
{children}
|
{children}
|
||||||
</DevisionLayout>;
|
</DevisionLayout>
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,22 @@
|
|||||||
import { DevisionPage } from "@/module/division/ui/DevisionPage";
|
|
||||||
import { Stack } from "@mantine/core";
|
|
||||||
|
|
||||||
export default function Page() {
|
import { DivisionPage } from "@/module/division/ui/DivisionPage";
|
||||||
return <DevisionPage />
|
import { SimpleGrid, Skeleton, Stack } from "@mantine/core";
|
||||||
|
import { Suspense } from "react";
|
||||||
|
|
||||||
|
export default function Page({ params, searchParams }: { params: any, searchParams: any }) {
|
||||||
|
|
||||||
|
return <Suspense fallback={<Stack gap={"md"} p={"md"}>
|
||||||
|
<Skeleton h={75} />
|
||||||
|
<Skeleton h={100} />
|
||||||
|
<SimpleGrid cols={4} spacing={"md"}>
|
||||||
|
<Skeleton h={75} />
|
||||||
|
<Skeleton h={75} />
|
||||||
|
<Skeleton h={75} />
|
||||||
|
<Skeleton h={75} />
|
||||||
|
</SimpleGrid>
|
||||||
|
<Skeleton h={100} />
|
||||||
|
<Skeleton h={100} />
|
||||||
|
</Stack>}>
|
||||||
|
<DivisionPage params={params} searchParams={searchParams} />
|
||||||
|
</Suspense>
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { getCountDivision } from "@/module/division/lib/division/get_count_devision"
|
||||||
|
export async function GET() {
|
||||||
|
const countDivision = getCountDivision()
|
||||||
|
return Response.json({ count: countDivision })
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { getListAnggota } from "@/module/division/lib/division/get_list_anggota";
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const listAnggota = await getListAnggota()
|
||||||
|
return Response.json(listAnggota)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { getListDevision } from "@/module/division/lib/division/get_list_devision"
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const list_devision = await getListDevision()
|
||||||
|
return Response.json(list_devision)
|
||||||
|
}
|
||||||
6
src/app/api/(dev-test)/test-devision/list-group/route.ts
Normal file
6
src/app/api/(dev-test)/test-devision/list-group/route.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { getListGroup } from "@/module/division/lib/division/get_list_group"
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const listGroup = await getListGroup()
|
||||||
|
return Response.json(listGroup)
|
||||||
|
}
|
||||||
4
src/app/api/division/get/route.ts
Normal file
4
src/app/api/division/get/route.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { apiDivision } from "@/module/division/api/api_division";
|
||||||
|
export async function GET(req: Request) {
|
||||||
|
return apiDivision(req, "GET")
|
||||||
|
}
|
||||||
4
src/app/api/division/post/route.tsx
Normal file
4
src/app/api/division/post/route.tsx
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { apiDivision } from "@/module/division/api/api_division";
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
return apiDivision(req, "POST")
|
||||||
|
}
|
||||||
51
src/lib/apiFetch.ts
Normal file
51
src/lib/apiFetch.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
interface Params {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
token?: string;
|
||||||
|
body?: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function funPramas(url: string, method: string, params?: Params) {
|
||||||
|
const property: Record<string, any> = {};
|
||||||
|
if (params) {
|
||||||
|
if (params.searchParams) {
|
||||||
|
property.searchParams =
|
||||||
|
"?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.body) {
|
||||||
|
property.body = JSON.stringify(params.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.token) {
|
||||||
|
property.headers.Authorization = `Bearer ${params.token}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property.method = method;
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${url}${property?.searchParams || ""}`, property);
|
||||||
|
return await res.json().catch(() => null);
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const apiPathTestDevisionListGroupGET = () =>
|
||||||
|
`/api/test-devision/list-group/`;
|
||||||
|
export const apiFetchTestDevisionListGroupGET = async (params?: Params) =>
|
||||||
|
funPramas(apiPathTestDevisionListGroupGET(), "GET", params);
|
||||||
|
|
||||||
|
export const apiPathTestDevisionListDivisionGET = () =>
|
||||||
|
`/api/test-devision/list-division/`;
|
||||||
|
export const apiFetchTestDevisionListDivisionGET = async (params?: Params) =>
|
||||||
|
funPramas(apiPathTestDevisionListDivisionGET(), "GET", params);
|
||||||
|
|
||||||
|
export const apiPathTestDevisionListAnggotaRouterTsGET = () =>
|
||||||
|
`/api/test-devision/list-anggota/router.ts`;
|
||||||
|
export const apiFetchTestDevisionListAnggotaRouterTsGET = async (
|
||||||
|
params?: Params,
|
||||||
|
) => funPramas(apiPathTestDevisionListAnggotaRouterTsGET(), "GET", params);
|
||||||
|
|
||||||
|
export const apiPathTestDevisionCountDevisionGET = () =>
|
||||||
|
`/api/test-devision/count-devision/`;
|
||||||
|
export const apiFetchTestDevisionCountDevisionGET = async (params?: Params) =>
|
||||||
|
funPramas(apiPathTestDevisionCountDevisionGET(), "GET", params);
|
||||||
111
src/lib/pagePath.ts
Normal file
111
src/lib/pagePath.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathPageTsx = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `page.tsx${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(dev-test)/test-division/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(dev-test)/test-division/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathTestDivision = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/test-division${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(auth)/welcome/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(auth)/welcome/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathWelcome = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/welcome${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(auth)/verification/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(auth)/verification/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathVerification = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/verification${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/search/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/search/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathSearch = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/search${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/profile/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/profile/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathProfile = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/profile${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/home/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/home/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathHome = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/home${searchParams}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* [/Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/detail-feature/page.tsx](file:///Users/bip/Documents/projects/bip/sistem-desa-mandiri/src/app/(application)/detail-feature/page.tsx)
|
||||||
|
*/
|
||||||
|
export const pagePathDetailFeature = (params?: {
|
||||||
|
searchParams?: Record<string, any>;
|
||||||
|
}) => {
|
||||||
|
let searchParams = "";
|
||||||
|
if (params && params.searchParams) {
|
||||||
|
searchParams = "?" + new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
return `/detail-feature${searchParams}`;
|
||||||
|
};
|
||||||
107
src/lib/stateApi.ts
Normal file
107
src/lib/stateApi.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
'use client';
|
||||||
|
import { State, hookstate, useHookstate } from '@hookstate/core';
|
||||||
|
|
||||||
|
const useState = <T>(s: State<T>) => {
|
||||||
|
const state = useHookstate(s);
|
||||||
|
const get = state.value;
|
||||||
|
const set = (v: typeof state.value) => state.set(v);
|
||||||
|
return [get, set] as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface ParamsLoad {
|
||||||
|
searchParams?: Record<string, string>
|
||||||
|
token?: string
|
||||||
|
body?: Record<string, any>
|
||||||
|
}
|
||||||
|
|
||||||
|
const funLoad = async (url: string, params?: ParamsLoad, set?: any, method?: string) => {
|
||||||
|
const property: Record<string, any> = {}
|
||||||
|
if(params) {
|
||||||
|
if(params.searchParams) {
|
||||||
|
property.searchParams = "?"+new URLSearchParams(params.searchParams).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params.body) {
|
||||||
|
property.body = JSON.stringify(params.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(params.token) {
|
||||||
|
property.headers.Authorization = `Bearer ${params.token}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
property.method = method;
|
||||||
|
const res = await fetch(url, property );
|
||||||
|
const json = await res.json().then((json) => json).catch(() => null);
|
||||||
|
if(json && set) set(json);
|
||||||
|
return {
|
||||||
|
res,
|
||||||
|
json
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const testDevisionListGroup = hookstate<any | undefined>(undefined);
|
||||||
|
export const ProviderTestDevisionListGroup = ({data}: {data: any}) => {
|
||||||
|
if(data && testDevisionListGroup.value === undefined) {
|
||||||
|
testDevisionListGroup.set(data)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
export const useTestDevisionListGroup = <T>() => {
|
||||||
|
|
||||||
|
const [get, set] = useState(useHookstate(testDevisionListGroup))
|
||||||
|
const load = (params?: ParamsLoad) => funLoad(`/api/test-devision/list-group/`,params, set, "GET")
|
||||||
|
const value: T = get
|
||||||
|
return [value, set, load] as const
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const testDevisionListDivision = hookstate<any | undefined>(undefined);
|
||||||
|
export const ProviderTestDevisionListDivision = ({data}: {data: any}) => {
|
||||||
|
if(data && testDevisionListDivision.value === undefined) {
|
||||||
|
testDevisionListDivision.set(data)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
export const useTestDevisionListDivision = <T>() => {
|
||||||
|
|
||||||
|
const [get, set] = useState(useHookstate(testDevisionListDivision))
|
||||||
|
const load = (params?: ParamsLoad) => funLoad(`/api/test-devision/list-division/`,params, set, "GET")
|
||||||
|
const value: T = get
|
||||||
|
return [value, set, load] as const
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const testDevisionListAnggota = hookstate<any | undefined>(undefined);
|
||||||
|
export const ProviderTestDevisionListAnggota = ({data}: {data: any}) => {
|
||||||
|
if(data && testDevisionListAnggota.value === undefined) {
|
||||||
|
testDevisionListAnggota.set(data)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
export const useTestDevisionListAnggota = <T>() => {
|
||||||
|
|
||||||
|
const [get, set] = useState(useHookstate(testDevisionListAnggota))
|
||||||
|
const load = (params?: ParamsLoad) => funLoad(`/api/test-devision/list-anggota/`,params, set, "GET")
|
||||||
|
const value: T = get
|
||||||
|
return [value, set, load] as const
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const testDevisionCountDevision = hookstate<any | undefined>(undefined);
|
||||||
|
export const ProviderTestDevisionCountDevision = ({data}: {data: any}) => {
|
||||||
|
if(data && testDevisionCountDevision.value === undefined) {
|
||||||
|
testDevisionCountDevision.set(data)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
export const useTestDevisionCountDevision = <T>() => {
|
||||||
|
|
||||||
|
const [get, set] = useState(useHookstate(testDevisionCountDevision))
|
||||||
|
const load = (params?: ParamsLoad) => funLoad(`/api/test-devision/count-devision/`,params, set, "GET")
|
||||||
|
const value: T = get
|
||||||
|
return [value, set, load] as const
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
16
src/module/division/api/api_division.ts
Normal file
16
src/module/division/api/api_division.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
type Method = "GET" | "POST"
|
||||||
|
|
||||||
|
const listApi = [
|
||||||
|
{
|
||||||
|
"page": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export async function apiDivision(req: Request, method: Method) {
|
||||||
|
const { searchParams } = new URL(req.url)
|
||||||
|
const page = searchParams.get("page")
|
||||||
|
|
||||||
|
if (!page) return Response.json({ message: "page not found" }, { status: 404 })
|
||||||
|
|
||||||
|
return Response.json({ message: "ok" })
|
||||||
|
}
|
||||||
68
src/module/division/component/BottomDrawer.tsx
Normal file
68
src/module/division/component/BottomDrawer.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
'use client'
|
||||||
|
import { ActionIcon, Drawer, Flex, Stack, Text } from "@mantine/core";
|
||||||
|
import { MdAddCircle, MdClose, MdFileCopy, MdSort } from "react-icons/md";
|
||||||
|
import { pagePathTestDivision } from "@/lib/pagePath";
|
||||||
|
|
||||||
|
export function BottomDrawer({ openDrawer, setOpenDrawer }: { openDrawer: boolean, setOpenDrawer: any }) {
|
||||||
|
|
||||||
|
function onAddDivisi() {
|
||||||
|
window.location.href = pagePathTestDivision({ searchParams: { page: "division-create" } })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDivisionFilter() {
|
||||||
|
window.location.href = pagePathTestDivision({ searchParams: { page: "division-filter" } })
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDivisionReport() {
|
||||||
|
window.location.href = pagePathTestDivision({ searchParams: { page: "division-report" } })
|
||||||
|
}
|
||||||
|
return <Drawer
|
||||||
|
p={0}
|
||||||
|
opened={openDrawer}
|
||||||
|
onClose={() => setOpenDrawer(false)}
|
||||||
|
position="bottom"
|
||||||
|
withCloseButton={false}
|
||||||
|
styles={{
|
||||||
|
content: {
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: 550,
|
||||||
|
height: 200,
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
borderTopLeftRadius: 20
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
>
|
||||||
|
<Stack gap={"md"}>
|
||||||
|
<Flex justify="space-between">
|
||||||
|
<Flex justify={"end"}>
|
||||||
|
<Text>Menu</Text>
|
||||||
|
</Flex>
|
||||||
|
<ActionIcon onClick={() => setOpenDrawer(false)} variant="subtle">
|
||||||
|
<MdClose />
|
||||||
|
</ActionIcon>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex gap={"md"} justify={"space-evenly"}>
|
||||||
|
<Stack align="center">
|
||||||
|
<ActionIcon onClick={onAddDivisi} size={"xl"} variant="subtle">
|
||||||
|
<MdAddCircle size={32} />
|
||||||
|
</ActionIcon>
|
||||||
|
<Text>Tambah Divisi</Text>
|
||||||
|
</Stack>
|
||||||
|
<Stack align="center">
|
||||||
|
<ActionIcon onClick={onDivisionFilter} size={"xl"} variant="subtle">
|
||||||
|
<MdSort size={32} />
|
||||||
|
</ActionIcon>
|
||||||
|
<Text>Filter</Text>
|
||||||
|
</Stack>
|
||||||
|
<Stack align="center">
|
||||||
|
<ActionIcon onClick={onDivisionReport} variant="subtle" size={"xl"}>
|
||||||
|
<MdFileCopy size={32} />
|
||||||
|
</ActionIcon>
|
||||||
|
<Text>Report</Text>
|
||||||
|
</Stack>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</Drawer>
|
||||||
|
}
|
||||||
26
src/module/division/component/ContainerDivision.tsx
Normal file
26
src/module/division/component/ContainerDivision.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { Box } from "@mantine/core"
|
||||||
|
import _ from "lodash"
|
||||||
|
import { DivisionCreate } from "../ui/DivisionCreate"
|
||||||
|
import { DivisionFilter } from "../ui/DivisionFilter"
|
||||||
|
import { DivisionReport } from "../ui/DivisionReport"
|
||||||
|
import { HeadDivision } from "./HeadDivision"
|
||||||
|
import { ListWithSearch } from "./ListWithSearch"
|
||||||
|
import { DivisionView } from "../ui/DivisionView"
|
||||||
|
|
||||||
|
|
||||||
|
const listPage = ["division", "division-create", "division-filter", "division-report"]
|
||||||
|
export function ContainerDevision({ params, searchParams, list_devision, countDevision }: { params: any, searchParams: any, list_devision: any[], countDevision: any }) {
|
||||||
|
const page = searchParams.page || "division"
|
||||||
|
const division = list_devision.map((v) => ({ ...v, name: _.kebabCase(v.name) })).find((v) => v.name === page) || null
|
||||||
|
return <Box>
|
||||||
|
<HeadDivision title={page} />
|
||||||
|
{/* {JSON.stringify(division)} */}
|
||||||
|
{page === "division" && <ListWithSearch count={countDevision} listData={list_devision} />}
|
||||||
|
{page === "division-create" && <DivisionCreate />}
|
||||||
|
{page === "division-filter" && <DivisionFilter />}
|
||||||
|
{page === "division-report" && <DivisionReport />}
|
||||||
|
{division && division.name === page && <DivisionView id={division.id} />}
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
36
src/module/division/component/HeadDivision.tsx
Normal file
36
src/module/division/component/HeadDivision.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
'use client'
|
||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { ActionIcon, Box, Flex, Title } from "@mantine/core";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { MdArrowBackIos, MdMenu } from "react-icons/md";
|
||||||
|
import { useTitle } from "../lib/devision_state";
|
||||||
|
import { BottomDrawer } from "./BottomDrawer";
|
||||||
|
import { pagePathTestDivision } from "@/lib/pagePath";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
|
export function HeadDivision({ title }: { title: string }) {
|
||||||
|
const [openDrawer, setOpenDrawer] = useState(false)
|
||||||
|
|
||||||
|
function onBack() {
|
||||||
|
window.location.href = pagePathTestDivision()
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Box pos={"sticky"} top={0} bg={WARNA.biruTua} p={"lg"} style={{
|
||||||
|
borderBottomLeftRadius: 20,
|
||||||
|
borderBottomRightRadius: 20,
|
||||||
|
zIndex: 999,
|
||||||
|
boxShadow: "0px 4px 4px rgba(0, 0, 0, 0.25)"
|
||||||
|
}}>
|
||||||
|
<Flex justify={"space-between"}>
|
||||||
|
<ActionIcon onClick={onBack} bg={WARNA.bgIcon} radius={100}>
|
||||||
|
<MdArrowBackIos />
|
||||||
|
</ActionIcon>
|
||||||
|
<Title c={WARNA.bgWhite} order={3}>{_.startCase(title)}</Title>
|
||||||
|
<ActionIcon onClick={() => setOpenDrawer(true)} bg={WARNA.bgIcon} >
|
||||||
|
<MdMenu />
|
||||||
|
</ActionIcon>
|
||||||
|
</Flex>
|
||||||
|
<BottomDrawer openDrawer={openDrawer} setOpenDrawer={setOpenDrawer} />
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
11
src/module/division/component/ListDivision.tsx
Normal file
11
src/module/division/component/ListDivision.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Stack } from "@mantine/core";
|
||||||
|
import { ViewGrid } from "./ViewGrid";
|
||||||
|
import { ViewList } from "./ViewList";
|
||||||
|
|
||||||
|
export function ListDivision({ listData, isGrid }: { listData: any[], isGrid?: boolean }) {
|
||||||
|
return <Stack gap={"md"} p={"md"}>
|
||||||
|
{listData.map((v, k) => isGrid ? <ViewGrid v={v} key={k} /> : <ViewList v={v} key={k} />)}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
40
src/module/division/component/ListWithSearch.tsx
Normal file
40
src/module/division/component/ListWithSearch.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { Box, Card, Center, Flex, Stack, Text, Title } from "@mantine/core"
|
||||||
|
import { ListDivision } from "./ListDivision"
|
||||||
|
import { SearchDivision } from "./SearchDivision"
|
||||||
|
import { ToogleList } from "./ToogleList"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { useShallowEffect } from "@mantine/hooks"
|
||||||
|
import { WARNA } from "@/module/_global"
|
||||||
|
import { apiFetchTestDevisionListDivisionGET } from "@/lib/apiFetch"
|
||||||
|
|
||||||
|
|
||||||
|
export function ListWithSearch({ listData, count }: { listData: any[], count: number }) {
|
||||||
|
const [isGrid, setIsGrid] = useState(true)
|
||||||
|
const [search, setSearch] = useState("")
|
||||||
|
const [listDivision, setListDivision] = useState(listData)
|
||||||
|
|
||||||
|
useShallowEffect(() => {
|
||||||
|
apiFetchTestDevisionListDivisionGET().then(setListDivision)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
return <Stack>
|
||||||
|
<Flex align={"center"} p={"md"} gap={"md"}>
|
||||||
|
<SearchDivision setText={setSearch} text={search} />
|
||||||
|
<ToogleList isGrid={isGrid} setIsGrid={setIsGrid} />
|
||||||
|
</Flex>
|
||||||
|
<Box p={"md"}>
|
||||||
|
<Card p={"md"} bg={WARNA.biruTua}>
|
||||||
|
<Stack>
|
||||||
|
<Text size="md" fw={"bold"} c={WARNA.bgWhite}>Total Divisi</Text>
|
||||||
|
<Center>
|
||||||
|
<Title c={WARNA.bgWhite}>{count}</Title>
|
||||||
|
</Center>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
</Box>
|
||||||
|
<ListDivision listData={listDivision.filter((v) => v.name.toLowerCase().includes(search.toLowerCase()))} isGrid={isGrid} />
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
16
src/module/division/component/MorePeopleIcon.tsx
Normal file
16
src/module/division/component/MorePeopleIcon.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { WARNA } from "@/module/_global"
|
||||||
|
import { Avatar } from "@mantine/core"
|
||||||
|
import { MdAccountCircle, MdPeople } from "react-icons/md"
|
||||||
|
|
||||||
|
export function MorePeopleIcon() {
|
||||||
|
return <Avatar.Group>
|
||||||
|
<Avatar>
|
||||||
|
<MdAccountCircle size={32} color={WARNA.biruTua} />
|
||||||
|
</Avatar>
|
||||||
|
<Avatar>
|
||||||
|
+5
|
||||||
|
</Avatar>
|
||||||
|
</Avatar.Group>
|
||||||
|
}
|
||||||
8
src/module/division/component/SearchDivision.tsx
Normal file
8
src/module/division/component/SearchDivision.tsx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { TextInput } from "@mantine/core"
|
||||||
|
import { MdSearch } from "react-icons/md"
|
||||||
|
|
||||||
|
export function SearchDivision({ text, setText }: { text: string, setText: any }) {
|
||||||
|
return <TextInput onChange={(e) => setText(e.target.value)} value={text} radius={30} leftSection={<MdSearch />} placeholder="Cari Divisi" />
|
||||||
|
}
|
||||||
17
src/module/division/component/ToogleList.tsx
Normal file
17
src/module/division/component/ToogleList.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { ActionIcon, Box } from "@mantine/core"
|
||||||
|
import { useState } from "react"
|
||||||
|
import { MdGrid3X3, MdGridView, MdList, MdViewList } from "react-icons/md"
|
||||||
|
|
||||||
|
export function ToogleList({ isGrid, setIsGrid }: { isGrid: boolean, setIsGrid: any }) {
|
||||||
|
function onToogleList() {
|
||||||
|
setIsGrid(!isGrid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Box>
|
||||||
|
<ActionIcon variant="light" onClick={onToogleList}>
|
||||||
|
{isGrid ? <MdList size={24} /> : <MdGridView size={22} />}
|
||||||
|
</ActionIcon>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
36
src/module/division/component/ViewGrid.tsx
Normal file
36
src/module/division/component/ViewGrid.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { Stack, Box, Title, Group, Text, UnstyledButton } from "@mantine/core";
|
||||||
|
import { MorePeopleIcon } from "./MorePeopleIcon";
|
||||||
|
import { pagePathTestDivision } from "@/lib/pagePath";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
|
export function ViewGrid({ v }: { v: any }) {
|
||||||
|
return (
|
||||||
|
<UnstyledButton onClick={() => {
|
||||||
|
window.location.href = pagePathTestDivision({ searchParams: { page: _.kebabCase(v.name) } })
|
||||||
|
}}>
|
||||||
|
<Stack gap={0}>
|
||||||
|
<Box style={{
|
||||||
|
borderTopLeftRadius: 8,
|
||||||
|
borderTopRightRadius: 8
|
||||||
|
}} p={"xl"} bg={WARNA.biruTua}>
|
||||||
|
<Title style={{
|
||||||
|
textAlign: "center"
|
||||||
|
}} order={3} c={WARNA.bgWhite}>{v.name}</Title>
|
||||||
|
</Box>
|
||||||
|
<Box style={{
|
||||||
|
border: "1px solid " + WARNA.biruTua,
|
||||||
|
borderBottomLeftRadius: 8,
|
||||||
|
borderBottomRightRadius: 8
|
||||||
|
}} p={"md"}>
|
||||||
|
<Stack>
|
||||||
|
<Text pr={100}>{v.desc}</Text>
|
||||||
|
<Group justify="end">
|
||||||
|
<MorePeopleIcon />
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</UnstyledButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
23
src/module/division/component/ViewList.tsx
Normal file
23
src/module/division/component/ViewList.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { pagePathTestDivision } from "@/lib/pagePath";
|
||||||
|
import { Avatar, Flex, Stack, Text, Title, UnstyledButton } from "@mantine/core";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { MdPeople } from "react-icons/md";
|
||||||
|
|
||||||
|
export function ViewList({ v }: { v: any }) {
|
||||||
|
return (
|
||||||
|
<UnstyledButton onClick={() => {
|
||||||
|
window.location.href = pagePathTestDivision({ searchParams: { page: _.kebabCase(v.name) } })
|
||||||
|
}}>
|
||||||
|
<Stack py={"md"} style={{
|
||||||
|
borderBottom: "0.5px solid " + "gray"
|
||||||
|
}}>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
<Avatar bg={"orange"} color="white">
|
||||||
|
<MdPeople size={32} />
|
||||||
|
</Avatar>
|
||||||
|
<Text fw={"bold"}>{v.name}</Text>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</UnstyledButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
33
src/module/division/lib/BottomMenu.tsx
Normal file
33
src/module/division/lib/BottomMenu.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { ActionIcon, Drawer, Flex, Stack, Text } from "@mantine/core";
|
||||||
|
import { MdClose } from "react-icons/md";
|
||||||
|
|
||||||
|
export function BottomMenu({size, title, openDrawer, setOpenDrawer, children }: { size?: number | string, title?: string, openDrawer: boolean, setOpenDrawer: any, children: React.ReactNode }) {
|
||||||
|
return <Drawer
|
||||||
|
p={0}
|
||||||
|
opened={openDrawer}
|
||||||
|
onClose={() => setOpenDrawer(false)}
|
||||||
|
position="bottom"
|
||||||
|
withCloseButton={false}
|
||||||
|
size={size || "md"}
|
||||||
|
styles={{
|
||||||
|
content: {
|
||||||
|
margin: "0 auto",
|
||||||
|
maxWidth: 550,
|
||||||
|
borderTopRightRadius: 20,
|
||||||
|
borderTopLeftRadius: 20
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack gap={"md"}>
|
||||||
|
<Flex justify="space-between">
|
||||||
|
<Flex justify={"end"}>
|
||||||
|
<Text>{title || 'Menu'}</Text>
|
||||||
|
</Flex>
|
||||||
|
<ActionIcon onClick={() => setOpenDrawer(false)} variant="subtle">
|
||||||
|
<MdClose />
|
||||||
|
</ActionIcon>
|
||||||
|
</Flex>
|
||||||
|
{children}
|
||||||
|
</Stack>
|
||||||
|
</Drawer>
|
||||||
|
}
|
||||||
25
src/module/division/lib/ButtonConfirm.tsx
Normal file
25
src/module/division/lib/ButtonConfirm.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { Button, Flex, Stack, Text, UnstyledButton } from "@mantine/core";
|
||||||
|
import { BottomMenu } from "./BottomMenu";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function ButtonConfirm({ label, desc, onConfirm }: { label: string, desc: string, onConfirm: () => void }) {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
|
const onClickConfirm = () => {
|
||||||
|
setOpen(false)
|
||||||
|
onConfirm()
|
||||||
|
}
|
||||||
|
return <Stack>
|
||||||
|
<Button onClick={() => setOpen(true)} radius={50} color={WARNA.biruTua}>{label}</Button>
|
||||||
|
<BottomMenu size={"xs"} title="Konfirmasi" openDrawer={open} setOpenDrawer={setOpen}>
|
||||||
|
<Stack gap={"xl"}>
|
||||||
|
<Text>{desc}</Text>
|
||||||
|
<Flex justify={"end"} gap={"xl"}>
|
||||||
|
<UnstyledButton onClick={() => setOpen(false)}>Cancel</UnstyledButton>
|
||||||
|
<Button onClick={onClickConfirm} color={WARNA.biruTua}>Confirm</Button>
|
||||||
|
</Flex>
|
||||||
|
</Stack>
|
||||||
|
</BottomMenu>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
6
src/module/division/lib/ButtonNavi.tsx
Normal file
6
src/module/division/lib/ButtonNavi.tsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
import { Button } from "@mantine/core";
|
||||||
|
|
||||||
|
export function ButtonNavi({ children, onClick }: { children: React.ReactNode, onClick?: () => void }) {
|
||||||
|
return <Button radius={50} color={WARNA.biruTua} onClick={onClick}>{children}</Button>
|
||||||
|
}
|
||||||
53
src/module/division/lib/MultiSelectList.tsx
Normal file
53
src/module/division/lib/MultiSelectList.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
'use client'
|
||||||
|
import { ActionIcon, Anchor, Button, Card, Divider, Flex, Group, NavLink, Paper, ScrollArea, Select, Stack, Text, UnstyledButton } from "@mantine/core";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { MdArrowForwardIos, MdCheckBox, MdCheckBoxOutlineBlank } from "react-icons/md";
|
||||||
|
import { BottomMenu } from "./BottomMenu";
|
||||||
|
import { ButtonNavi } from "./ButtonNavi";
|
||||||
|
import _ from "lodash";
|
||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
|
||||||
|
export function MultiSelectList(
|
||||||
|
{ label, placeholder, data = [], listSelected = [], setListSelected }:
|
||||||
|
{ label?: string, placeholder?: string, data?: any[], listSelected: any[], setListSelected: any }
|
||||||
|
) {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
// const [listSelected, setListSelected] = useState(defaultValue)
|
||||||
|
|
||||||
|
function selected(value: { label: string, value: any }) {
|
||||||
|
if (listSelected.includes(value.value)) {
|
||||||
|
setListSelected(listSelected.filter((v) => v !== value.value))
|
||||||
|
} else {
|
||||||
|
setListSelected([...listSelected, value.value])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClickSimpan = () => {
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
return <Stack>
|
||||||
|
<UnstyledButton onClick={() => setOpen(true)}>
|
||||||
|
<Paper p={"sm"} withBorder radius={12}>
|
||||||
|
<Flex justify={"space-between"}>
|
||||||
|
<Text>{_.isEmpty(listSelected) ? "Pilih Anggota" : "Tambah Anggota"}</Text>
|
||||||
|
<MdArrowForwardIos size={"1.5rem"} />
|
||||||
|
</Flex>
|
||||||
|
</Paper>
|
||||||
|
</UnstyledButton>
|
||||||
|
<BottomMenu title="Pilih Anggota" openDrawer={open} setOpenDrawer={setOpen}>
|
||||||
|
<Stack>
|
||||||
|
<ScrollArea.Autosize mah={300} >
|
||||||
|
{data.map((v, k) => <Stack key={k} gap={"lg"}>
|
||||||
|
<NavLink
|
||||||
|
onClick={() => selected(v)}
|
||||||
|
leftSection={listSelected.includes(v.value) ? <MdCheckBox size={"1.5rem"} /> : <MdCheckBoxOutlineBlank size={"1.5rem"} />}
|
||||||
|
label={v.label} />
|
||||||
|
</Stack>)}
|
||||||
|
</ScrollArea.Autosize>
|
||||||
|
<Group justify="end">
|
||||||
|
<ButtonNavi onClick={onClickSimpan}>Simpan</ButtonNavi>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</BottomMenu>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
46
src/module/division/lib/SingleSelect.tsx
Normal file
46
src/module/division/lib/SingleSelect.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
'use client'
|
||||||
|
import { Flex, Group, NavLink, Paper, ScrollArea, Select, Stack, Text, UnstyledButton } from "@mantine/core";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { BottomMenu } from "./BottomMenu";
|
||||||
|
import { MdArrowForwardIos, MdCheckBox, MdCheckBoxOutlineBlank } from "react-icons/md";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
|
export function SingleSelect({ desc, icon, placeholder, selected, setSelected, data }: { desc?: string, icon?: any, placeholder: string, selected: any, setSelected: any, data: any[] }) {
|
||||||
|
const [open, setOpen] = useState(false)
|
||||||
|
const completed = desc && !_.isEmpty(data) && !_.isEmpty(selected)
|
||||||
|
|
||||||
|
const onSelected = (value: any) => {
|
||||||
|
setSelected(value)
|
||||||
|
setOpen(false)
|
||||||
|
}
|
||||||
|
return <Stack>
|
||||||
|
<UnstyledButton onClick={() => setOpen(true)} disabled={_.isEmpty(data)}>
|
||||||
|
<Paper p={"sm"} withBorder radius={12} bg={_.isEmpty(data) ? "transparent" : "white"}>
|
||||||
|
<Stack gap={ completed ? "sm" : 0}>
|
||||||
|
<Flex justify={"space-between"}>
|
||||||
|
<Flex gap={"md"} align={"center"}>
|
||||||
|
{icon && icon}
|
||||||
|
<Text c={_.isEmpty(selected) ? "dimmed" : "black"}>{!_.isEmpty(data) ? data?.filter((v) => v.value === selected)[0]?.label || placeholder : placeholder}</Text>
|
||||||
|
</Flex>
|
||||||
|
<MdArrowForwardIos color={_.isEmpty(data) ? "light" : "black"} size={"1.5rem"} />
|
||||||
|
</Flex>
|
||||||
|
{completed && <Group justify="end"><Text c="dimmed" size="sm">{desc}</Text></Group>}
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</UnstyledButton>
|
||||||
|
<BottomMenu openDrawer={open} setOpenDrawer={setOpen} >
|
||||||
|
<Stack>
|
||||||
|
<ScrollArea.Autosize mah={300} >
|
||||||
|
{data?.map((v, k) => <NavLink
|
||||||
|
onClick={() => onSelected(v.value)}
|
||||||
|
leftSection={selected === v.value ?
|
||||||
|
<MdCheckBox size={"1.5rem"} /> :
|
||||||
|
<MdCheckBoxOutlineBlank
|
||||||
|
size={"1.5rem"} />}
|
||||||
|
key={k}
|
||||||
|
label={v.label} />)}
|
||||||
|
</ScrollArea.Autosize>
|
||||||
|
</Stack>
|
||||||
|
</BottomMenu>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
12
src/module/division/lib/WebVitals.tsx
Normal file
12
src/module/division/lib/WebVitals.tsx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useReportWebVitals } from 'next/web-vitals';
|
||||||
|
|
||||||
|
export function WebVitals({ searchParams }: { searchParams: any }) {
|
||||||
|
const log = searchParams.log;
|
||||||
|
useReportWebVitals((metric) => {
|
||||||
|
log && console.log(JSON.stringify(metric, null, 4));
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
14
src/module/division/lib/devision_state.ts
Normal file
14
src/module/division/lib/devision_state.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { State, hookstate, useHookstate } from "@hookstate/core";
|
||||||
|
|
||||||
|
const useState = <T>(s: State<T>) => {
|
||||||
|
const state = useHookstate(s);
|
||||||
|
const get = state.value;
|
||||||
|
const set = (v: typeof state.value) => state.set(v);
|
||||||
|
return [get, set] as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
const title = hookstate("Divisi")
|
||||||
|
export const useTitle = () => useState<string>(title);
|
||||||
|
|
||||||
|
const filter = hookstate("")
|
||||||
|
export const useDivisionfilter = () => useState<string>(filter)
|
||||||
5
src/module/division/lib/division/get_count_devision.ts
Normal file
5
src/module/division/lib/division/get_count_devision.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { list_devision } from "@/dummy_data";
|
||||||
|
|
||||||
|
export async function getCountDivision() {
|
||||||
|
return list_devision.length
|
||||||
|
}
|
||||||
45
src/module/division/lib/division/get_list_anggota.ts
Normal file
45
src/module/division/lib/division/get_list_anggota.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
const listAnggota = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "Anggota 1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "Anggota 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "Anggota 3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "4",
|
||||||
|
name: "Anggota 4",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "5",
|
||||||
|
name: "Anggota 5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "6",
|
||||||
|
name: "Anggota 6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "7",
|
||||||
|
name: "Anggota 7",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "8",
|
||||||
|
name: "Anggota 8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "9",
|
||||||
|
name: "Anggota 9",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "10",
|
||||||
|
name: "Anggota 10",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
export async function getListAnggota() {
|
||||||
|
return listAnggota
|
||||||
|
}
|
||||||
5
src/module/division/lib/division/get_list_devision.ts
Normal file
5
src/module/division/lib/division/get_list_devision.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { list_devision } from "@/dummy_data";
|
||||||
|
|
||||||
|
export async function getListDevision() {
|
||||||
|
return list_devision
|
||||||
|
}
|
||||||
18
src/module/division/lib/division/get_list_group.ts
Normal file
18
src/module/division/lib/division/get_list_group.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
const listGroup = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "Group 1",
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "Group 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "3",
|
||||||
|
name: "Group 3",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
export async function getListGroup() {
|
||||||
|
return listGroup
|
||||||
|
}
|
||||||
20
src/module/division/lib/toast.tsx
Normal file
20
src/module/division/lib/toast.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { WARNA } from '@/module/_global'
|
||||||
|
import t from 'react-simple-toasts'
|
||||||
|
|
||||||
|
type Event = "error" | "success" | "info" | "warning"
|
||||||
|
export const toast = (message: string, event?: Event) => {
|
||||||
|
t(message, {
|
||||||
|
position: "center",
|
||||||
|
render: (message) => <div style={{
|
||||||
|
padding: 12,
|
||||||
|
paddingLeft: 24,
|
||||||
|
paddingRight: 24,
|
||||||
|
borderRadius: "100px",
|
||||||
|
backgroundColor: event === "error" ? "red" : event === "success" ? "green" : event === "warning" ? "orange" : WARNA.biruTua,
|
||||||
|
color: "white",
|
||||||
|
boxShadow: "0px 0px 10px rgba(0, 0, 0, 0.3)",
|
||||||
|
}}>
|
||||||
|
<div >{message?.toString()}</div>
|
||||||
|
</div>,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { Stack } from "@mantine/core";
|
|
||||||
|
|
||||||
export function DevisionPage() {
|
|
||||||
return <Stack>
|
|
||||||
|
|
||||||
</Stack>;
|
|
||||||
}
|
|
||||||
81
src/module/division/ui/DivisionCreate.tsx
Normal file
81
src/module/division/ui/DivisionCreate.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { ActionIcon, Avatar, Button, Card, Flex, ScrollArea, Select, Stack, Text, TextInput, Textarea } from "@mantine/core"
|
||||||
|
import { MultiSelectList } from "../lib/MultiSelectList"
|
||||||
|
import { WARNA } from "@/module/_global"
|
||||||
|
import { useTestDevisionListAnggota, useTestDevisionListGroup } from "@/lib/stateApi"
|
||||||
|
import { useState } from "react"
|
||||||
|
import _ from "lodash"
|
||||||
|
import { MdAccountCircle, MdClose, MdGroup, MdGroupAdd, MdGroupWork, MdShield } from "react-icons/md"
|
||||||
|
import { ButtonNavi } from "../lib/ButtonNavi"
|
||||||
|
import { pagePathTestDivision } from "@/lib/pagePath"
|
||||||
|
import { SingleSelect } from "../lib/SingleSelect"
|
||||||
|
import { ButtonConfirm } from "../lib/ButtonConfirm"
|
||||||
|
import { toast } from "../lib/toast"
|
||||||
|
|
||||||
|
|
||||||
|
export function DivisionCreate() {
|
||||||
|
const [val, setVal, load] = useTestDevisionListGroup<any[]>()
|
||||||
|
const [listAnggota, setListAnggota] = useTestDevisionListAnggota<any[]>()
|
||||||
|
const [listSelectedAnggota, setListSelectedAnggota] = useState<any[]>([])
|
||||||
|
const [selectedAdmin, setSelectedAdmin] = useState("")
|
||||||
|
const [selectedGroup, setSelectedGroup] = useState("")
|
||||||
|
|
||||||
|
return <Stack p={"md"} gap={"md"} >
|
||||||
|
<SingleSelect
|
||||||
|
desc="Pilih Grup"
|
||||||
|
icon={<MdGroupWork size={"1.5rem"} />}
|
||||||
|
selected={selectedGroup}
|
||||||
|
setSelected={setSelectedGroup}
|
||||||
|
data={val && val.map((v) => ({ label: v.name, value: v.id }))}
|
||||||
|
placeholder="Pilih Grup" />
|
||||||
|
<TextInput
|
||||||
|
size="md"
|
||||||
|
withAsterisk
|
||||||
|
radius={12}
|
||||||
|
placeholder="Nama"
|
||||||
|
label="Masukan Nama" />
|
||||||
|
<Textarea
|
||||||
|
size="md"
|
||||||
|
withAsterisk
|
||||||
|
radius={12}
|
||||||
|
autosize
|
||||||
|
minRows={6}
|
||||||
|
maxRows={12}
|
||||||
|
placeholder="Masukan Deskripsi"
|
||||||
|
label="Masukan Deskripsi" />
|
||||||
|
<MultiSelectList setListSelected={setListSelectedAnggota} listSelected={listSelectedAnggota} placeholder="Pilih Anggota" data={listAnggota.map((v) => ({ label: v.name, value: v.id }))} />
|
||||||
|
<SelectedAnggotaContainer setListSelectedAnggota={setListSelectedAnggota} listSelectedAnggota={listSelectedAnggota} listAnggota={listAnggota} />
|
||||||
|
<SingleSelect desc="Pilih Admin" icon={<MdShield size={"1.5rem"} />} selected={selectedAdmin} setSelected={setSelectedAdmin} data={listAnggota.filter((v) => listSelectedAnggota.includes(v.id)).map((v) => ({ label: v.name, value: v.id }))} placeholder="Select Admin" />
|
||||||
|
<ButtonConfirm onConfirm={() => {
|
||||||
|
toast("Simpan Berhasil", "success")
|
||||||
|
}} label="Simpan" desc="Apakah anda yakin ingin menyimpan data?" />
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
|
|
||||||
|
function SelectedAnggotaContainer({ listSelectedAnggota, listAnggota, setListSelectedAnggota }: { listSelectedAnggota: any[], listAnggota?: any[], setListSelectedAnggota: any }) {
|
||||||
|
if (_.isEmpty(listSelectedAnggota)) return null
|
||||||
|
return <Card>
|
||||||
|
<Stack>
|
||||||
|
<Flex justify={"space-between"}>
|
||||||
|
<Text>Anggota Terpilih</Text>
|
||||||
|
<Text>Total: {listSelectedAnggota.length}</Text>
|
||||||
|
</Flex>
|
||||||
|
<ScrollArea.Autosize mah={200}>
|
||||||
|
{listAnggota?.filter((v) => listSelectedAnggota.includes(v.id)).map((v, k) => <Stack py={"sm"} key={k}>
|
||||||
|
<Flex align={"center"} gap={"md"} justify={"space-between"}>
|
||||||
|
<Flex gap={"md"}>
|
||||||
|
<Avatar size={"md"} color={WARNA.biruTua}><MdAccountCircle /></Avatar><Text>{v.name}</Text>
|
||||||
|
</Flex>
|
||||||
|
<ActionIcon onClick={() => {
|
||||||
|
setListSelectedAnggota((prev: any) => prev.filter((val: any) => val !== v.id))
|
||||||
|
}} variant="subtle">
|
||||||
|
<MdClose />
|
||||||
|
</ActionIcon>
|
||||||
|
</Flex>
|
||||||
|
</Stack>)}
|
||||||
|
</ScrollArea.Autosize>
|
||||||
|
</Stack>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
}
|
||||||
22
src/module/division/ui/DivisionFilter.tsx
Normal file
22
src/module/division/ui/DivisionFilter.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Button, Divider, Flex, ScrollArea, Stack, Text } from "@mantine/core";
|
||||||
|
import { useDivisionfilter } from "../lib/devision_state";
|
||||||
|
import { useTestDevisionListDivision } from "@/lib/stateApi";
|
||||||
|
import { WARNA } from "@/module/_global";
|
||||||
|
|
||||||
|
export function DivisionFilter() {
|
||||||
|
const [filterText, setFilterText] = useDivisionfilter()
|
||||||
|
const [listDevision, setListDevision] = useTestDevisionListDivision<any[]>()
|
||||||
|
return <Stack>
|
||||||
|
{/* {listDevision.map((v, k) => <ViewList key={k} v={v} />)} */}
|
||||||
|
<Button color={WARNA.biruTua} radius={100}>Terapkan</Button>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
|
|
||||||
|
function ViewList({ v }: { v: any }) {
|
||||||
|
return <Stack gap={0}>
|
||||||
|
<Flex p={"md"}>
|
||||||
|
<Text>{v.name}</Text>
|
||||||
|
</Flex>
|
||||||
|
<Divider />
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
export function DevisionLayout({ children }: { children: React.ReactNode }) {
|
export function DevisionLayout({ children }: { children: React.ReactNode }) {
|
||||||
return <>{children}</>;
|
return <div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
21
src/module/division/ui/DivisionPage.tsx
Normal file
21
src/module/division/ui/DivisionPage.tsx
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
import { getCountDivision } from "@/module/division/lib/division/get_count_devision";
|
||||||
|
import { getListDevision } from "@/module/division/lib/division/get_list_devision";
|
||||||
|
import { ContainerDevision } from "../component/ContainerDivision";
|
||||||
|
import { WebVitals } from "../lib/WebVitals";
|
||||||
|
import { ProviderTestDevisionListAnggota, ProviderTestDevisionListDivision, ProviderTestDevisionListGroup } from "@/lib/stateApi";
|
||||||
|
import { getListGroup } from "../lib/division/get_list_group";
|
||||||
|
import { getListAnggota } from "../lib/division/get_list_anggota";
|
||||||
|
export async function DivisionPage({ params, searchParams }: { params: any, searchParams: any }) {
|
||||||
|
const list_devision = await getListDevision();
|
||||||
|
const countDevision = await getCountDivision()
|
||||||
|
const listGroup = await getListGroup()
|
||||||
|
const listAnggota = await getListAnggota()
|
||||||
|
return <div>
|
||||||
|
<WebVitals searchParams={searchParams} />
|
||||||
|
<ProviderTestDevisionListDivision data={list_devision} />
|
||||||
|
<ProviderTestDevisionListGroup data={listGroup} />
|
||||||
|
<ProviderTestDevisionListAnggota data={listAnggota} />
|
||||||
|
<ContainerDevision params={params} searchParams={searchParams} list_devision={list_devision} countDevision={countDevision} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
5
src/module/division/ui/DivisionReport.tsx
Normal file
5
src/module/division/ui/DivisionReport.tsx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export function DivisionReport() {
|
||||||
|
return <div>
|
||||||
|
report
|
||||||
|
</div>
|
||||||
|
}
|
||||||
10
src/module/division/ui/DivisionView.tsx
Normal file
10
src/module/division/ui/DivisionView.tsx
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
'use client'
|
||||||
|
import { Stack } from "@mantine/core";
|
||||||
|
|
||||||
|
export function DivisionView({ id }: { id: string }) {
|
||||||
|
return (
|
||||||
|
<Stack>
|
||||||
|
division view
|
||||||
|
</Stack>
|
||||||
|
)
|
||||||
|
}
|
||||||
43
yarn.lock
43
yarn.lock
@@ -89,6 +89,16 @@
|
|||||||
resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz"
|
resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.4.tgz"
|
||||||
integrity sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==
|
integrity sha512-dWO2pw8hhi+WrXq1YJy2yCuWoL20PddgGaqTgVe4cOS9Q6qklXCiA1tJEqX6BEwRNSCP84/afac9hd4MS+zEUA==
|
||||||
|
|
||||||
|
"@hookstate/core@^4.0.1":
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hookstate/core/-/core-4.0.1.tgz#6744380e96ce13fe3488c926c1cbae93bbea0ff6"
|
||||||
|
integrity sha512-Uh2D8Z0z/pqOJ7t+SfC+2sj13JQcB4yFhtL+T1choCaBxTSlgOS/CKRBohgJ4cjTKoxOmTT8uSQysu3gUjX+Gw==
|
||||||
|
|
||||||
|
"@hookstate/localstored@^4.0.2":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hookstate/localstored/-/localstored-4.0.2.tgz#6f0ef6b71baa4c28e5e8835431585500eb6a9532"
|
||||||
|
integrity sha512-81dbUH6xnwbePby21NQN8zrmjvMA8tOYeOOLZXqRmRGKnhtcokjTJoRNMZugpC9P3/NnacllBZ5ZUt43nmrKkA==
|
||||||
|
|
||||||
"@humanwhocodes/config-array@^0.11.14":
|
"@humanwhocodes/config-array@^0.11.14":
|
||||||
version "0.11.14"
|
version "0.11.14"
|
||||||
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz"
|
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz"
|
||||||
@@ -638,6 +648,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
|
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
|
||||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||||
|
|
||||||
|
"@types/lodash@^4.17.6":
|
||||||
|
version "4.17.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.6.tgz#193ced6a40c8006cfc1ca3f4553444fb38f0e543"
|
||||||
|
integrity sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==
|
||||||
|
|
||||||
"@types/node@^20.14.9":
|
"@types/node@^20.14.9":
|
||||||
version "20.14.9"
|
version "20.14.9"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz"
|
||||||
@@ -2370,7 +2385,7 @@ lodash.merge@^4.6.2:
|
|||||||
|
|
||||||
lodash@^4.17.21:
|
lodash@^4.17.21:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||||
@@ -2845,6 +2860,11 @@ react-remove-scroll@^2.5.7:
|
|||||||
use-callback-ref "^1.3.0"
|
use-callback-ref "^1.3.0"
|
||||||
use-sidecar "^1.1.2"
|
use-sidecar "^1.1.2"
|
||||||
|
|
||||||
|
react-simple-toasts@^5.10.0:
|
||||||
|
version "5.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-simple-toasts/-/react-simple-toasts-5.10.0.tgz#cfa692cd06fe858ea327adf32e72db2199459fa7"
|
||||||
|
integrity sha512-GIsBaLkZnyqeTzs0fSmXoLr5GtSnHv9C35tEx/2mc8H7/OaTlwXRHjm0ssDP454gvI4rZFS+rnj2HOL5zuiiwA==
|
||||||
|
|
||||||
react-smooth@^4.0.0:
|
react-smooth@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz"
|
resolved "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz"
|
||||||
@@ -3106,8 +3126,16 @@ streamsearch@^1.1.0:
|
|||||||
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
|
||||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
"string-width-cjs@npm:string-width@^4.2.0":
|
||||||
name string-width-cjs
|
version "4.2.3"
|
||||||
|
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||||
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
|
dependencies:
|
||||||
|
emoji-regex "^8.0.0"
|
||||||
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
strip-ansi "^6.0.1"
|
||||||
|
|
||||||
|
string-width@^4.1.0:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -3179,7 +3207,14 @@ string.prototype.trimstart@^1.0.8:
|
|||||||
define-properties "^1.2.1"
|
define-properties "^1.2.1"
|
||||||
es-object-atoms "^1.0.0"
|
es-object-atoms "^1.0.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^5.0.1"
|
||||||
|
|
||||||
|
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
|
|||||||
Reference in New Issue
Block a user