This commit is contained in:
@@ -9,6 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { useAlertStore, useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import {
|
||||
type DesignCnstnApplySaveRequestDto,
|
||||
designCnstnKeys,
|
||||
@@ -167,6 +168,9 @@ function DesignFormPage({ mode, initialData, createDefaults }: DesignFormPagePro
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-6 space-y-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
{initialData?.detDto?.designCnstnDocNo && (
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
@@ -208,13 +212,20 @@ function DesignFormPage({ mode, initialData, createDefaults }: DesignFormPagePro
|
||||
>
|
||||
신청완료
|
||||
</Button>
|
||||
<Button color="red" type="button" onClick={handleDelClick} disabled={isSubmitting}>
|
||||
<Button
|
||||
color="red"
|
||||
type="button"
|
||||
onClick={handleDelClick}
|
||||
disabled={isSubmitting}
|
||||
>
|
||||
삭제
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useMemo, useRef } from "react";
|
||||
|
||||
import { useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { useDesignCnstnMng } from "@/entities/design-cnstn";
|
||||
import { ElaprDocPrgrsStatus } from "@/entities/elapr";
|
||||
import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw";
|
||||
@@ -80,7 +81,10 @@ function DesignViewPage({ id }: DesignViewPageProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-4">
|
||||
<div className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
sttsChgHstryList={sttsChgHstryList}
|
||||
@@ -110,6 +114,8 @@ function DesignViewPage({ id }: DesignViewPageProps) {
|
||||
opnrNm={userInfo?.userName}
|
||||
/>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { useAlertStore, useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { useAcntgSeMngTree } from "@/entities/acntg";
|
||||
import { useEsntlAtchFileMngTree } from "@/entities/esntl";
|
||||
import {
|
||||
@@ -259,7 +260,10 @@ function FnrsFormPage({ mode, initialData, createDefaults }: FnrsFormPageProps)
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-6 space-y-4">
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
{initialData?.detDto?.fnrsCnsltnDocNo && (
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
@@ -332,6 +336,8 @@ function FnrsFormPage({ mode, initialData, createDefaults }: FnrsFormPageProps)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
import { useMemo, useRef } from "react";
|
||||
|
||||
import { useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { ElaprDocPrgrsStatus } from "@/entities/elapr";
|
||||
import { useFnrsCnsltnMng } from "@/entities/fnrs-cnsltn";
|
||||
import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw";
|
||||
import { AttachmentsViewSection, ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt";
|
||||
import {
|
||||
AttachmentsViewSection,
|
||||
ProgressStatusSection,
|
||||
SupplementDemandSection,
|
||||
} from "@/widgets/pbadms-sprt";
|
||||
import { Skeleton } from "@common/components";
|
||||
|
||||
import { needsRoleUser01AtrzResolve } from "../lib/button-config";
|
||||
@@ -90,7 +95,10 @@ function FnrsViewPage({ id }: FnrsViewPageProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-4">
|
||||
<div className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
sttsChgHstryList={sttsChgHstryList}
|
||||
@@ -131,6 +139,8 @@ function FnrsViewPage({ id }: FnrsViewPageProps) {
|
||||
opnrNm={userInfo?.userName}
|
||||
/>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { useAlertStore, useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { useEsntlAtchFileMngTree } from "@/entities/esntl";
|
||||
import {
|
||||
type InstlSncnApplySaveRequestDto,
|
||||
@@ -222,7 +223,10 @@ function InstlFormPage({ mode, initialData, createDefaults }: InstlFormPageProps
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-6 space-y-4">
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
{initialData?.detDto.instlSncnDocNo && (
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
@@ -291,6 +295,8 @@ function InstlFormPage({ mode, initialData, createDefaults }: InstlFormPageProps
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
import { useMemo, useRef } from "react";
|
||||
|
||||
import { useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { ElaprDocPrgrsStatus } from "@/entities/elapr";
|
||||
import { useInstlSncnDetail } from "@/entities/instl-sncn";
|
||||
import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw";
|
||||
import { AttachmentsViewSection, ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt";
|
||||
import {
|
||||
AttachmentsViewSection,
|
||||
ProgressStatusSection,
|
||||
SupplementDemandSection,
|
||||
} from "@/widgets/pbadms-sprt";
|
||||
import { Skeleton } from "@common/components";
|
||||
|
||||
import { needsRoleUser01AtrzResolve } from "../lib/button-config";
|
||||
@@ -88,7 +93,10 @@ function InstlViewPage({ id }: InstlViewPageProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-4">
|
||||
<div className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
sttsChgHstryList={sttsChgHstryList}
|
||||
@@ -131,6 +139,8 @@ function InstlViewPage({ id }: InstlViewPageProps) {
|
||||
opnrNm={userInfo?.userName}
|
||||
/>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { useAlertStore, useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { useAcntgSeMngTree } from "@/entities/acntg";
|
||||
import { useEsntlAtchFileMngTree } from "@/entities/esntl";
|
||||
import {
|
||||
@@ -240,6 +241,9 @@ function SewerBscPlanFormPage({
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSave)} className="mt-6 space-y-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
{initialData?.detDto?.sewerBscPlanDocNo && (
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
@@ -310,6 +314,8 @@ function SewerBscPlanFormPage({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
import { useMemo, useRef } from "react";
|
||||
|
||||
import { useUserStore } from "@/shared/lib";
|
||||
import { SectionCollapsibleGroup, SectionCollapsibleToggle } from "@/shared/ui";
|
||||
import { ElaprDocPrgrsStatus } from "@/entities/elapr";
|
||||
import { useRvwMnpwMngLoginUserList } from "@/entities/rvw-mnpw";
|
||||
import { useSewerBscPlanDetails } from "@/entities/sewer-bsc-plan";
|
||||
import { AttachmentsViewSection, ProgressStatusSection, SupplementDemandSection } from "@/widgets/pbadms-sprt";
|
||||
import {
|
||||
AttachmentsViewSection,
|
||||
ProgressStatusSection,
|
||||
SupplementDemandSection,
|
||||
} from "@/widgets/pbadms-sprt";
|
||||
import { Skeleton } from "@common/components";
|
||||
|
||||
import { needsRoleUser01AtrzResolve } from "../lib/button-config";
|
||||
@@ -95,7 +100,10 @@ function SewerBscPlanViewPage({ id, propChgCycl }: SewerBscPlanViewPageProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mt-6 space-y-4">
|
||||
<div className="mt-4">
|
||||
<SectionCollapsibleGroup>
|
||||
<SectionCollapsibleToggle />
|
||||
<div className="space-y-4">
|
||||
<ProgressStatusSection
|
||||
columns={PROGRESS_STATUS_COLUMNS}
|
||||
sttsChgHstryList={sttsChgHstryList}
|
||||
@@ -138,6 +146,8 @@ function SewerBscPlanViewPage({ id, propChgCycl }: SewerBscPlanViewPageProps) {
|
||||
opnrNm={userInfo?.userName}
|
||||
/>
|
||||
</div>
|
||||
</SectionCollapsibleGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
export { NoData } from "./no-data";
|
||||
export { PageLayout } from "./page-layout";
|
||||
export { SectionCollapsible } from "./section-collapsible";
|
||||
export {
|
||||
SectionCollapsibleGroup,
|
||||
SectionCollapsibleToggle,
|
||||
} from "./section-collapsible-group";
|
||||
export type { TextShimmerProps } from "./text-shimmer";
|
||||
export { TEXT_SHIMMER_CLASS, TextShimmer } from "./text-shimmer";
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, type ReactNode, useCallback, useContext, useMemo, useState } from "react";
|
||||
|
||||
import { ChevronsDownUp, ChevronsUpDown } from "lucide-react";
|
||||
|
||||
import { Button } from "@common/components";
|
||||
|
||||
interface SectionCollapsibleGroupValue {
|
||||
batchOpen: boolean;
|
||||
batchVersion: number;
|
||||
expandAll: () => void;
|
||||
collapseAll: () => void;
|
||||
}
|
||||
|
||||
const SectionCollapsibleGroupContext = createContext<SectionCollapsibleGroupValue | null>(null);
|
||||
|
||||
function useSectionCollapsibleGroup() {
|
||||
return useContext(SectionCollapsibleGroupContext);
|
||||
}
|
||||
|
||||
interface SectionCollapsibleGroupProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
function SectionCollapsibleGroup({ children }: SectionCollapsibleGroupProps) {
|
||||
const [batch, setBatch] = useState({ open: true, version: 0 });
|
||||
|
||||
const expandAll = useCallback(() => {
|
||||
setBatch((prev) => ({ open: true, version: prev.version + 1 }));
|
||||
}, []);
|
||||
|
||||
const collapseAll = useCallback(() => {
|
||||
setBatch((prev) => ({ open: false, version: prev.version + 1 }));
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
batchOpen: batch.open,
|
||||
batchVersion: batch.version,
|
||||
expandAll,
|
||||
collapseAll,
|
||||
}),
|
||||
[batch.open, batch.version, expandAll, collapseAll],
|
||||
);
|
||||
|
||||
return (
|
||||
<SectionCollapsibleGroupContext.Provider value={value}>
|
||||
{children}
|
||||
</SectionCollapsibleGroupContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function SectionCollapsibleToggle() {
|
||||
const group = useSectionCollapsibleGroup();
|
||||
|
||||
if (!group) return null;
|
||||
|
||||
const { batchOpen, expandAll, collapseAll } = group;
|
||||
|
||||
return (
|
||||
<div className="sticky top-[6rem] z-30 flex justify-start gap-2 bg-container px-4 py-2">
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color="white"
|
||||
className="gap-1 px-4 tracking-tight"
|
||||
aria-expanded={batchOpen}
|
||||
onClick={collapseAll}
|
||||
>
|
||||
<ChevronsDownUp className="shrink-0" />
|
||||
전체접기
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="sm"
|
||||
color="white"
|
||||
className="gap-1 px-4 tracking-tight"
|
||||
aria-expanded={batchOpen}
|
||||
onClick={expandAll}
|
||||
>
|
||||
<ChevronsUpDown className="shrink-0" />
|
||||
전체펼침
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export { SectionCollapsibleGroup, SectionCollapsibleToggle, useSectionCollapsibleGroup };
|
||||
@@ -1,11 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { type ReactNode, useState } from "react";
|
||||
|
||||
import { ChevronDown } from "lucide-react";
|
||||
|
||||
import { cn, Collapsible, CollapsibleContent, CollapsibleTrigger } from "@common/components";
|
||||
|
||||
import { useSectionCollapsibleGroup } from "./section-collapsible-group";
|
||||
|
||||
interface SectionCollapsibleProps {
|
||||
title: ReactNode;
|
||||
defaultOpen?: boolean;
|
||||
@@ -13,8 +15,19 @@ interface SectionCollapsibleProps {
|
||||
}
|
||||
|
||||
function SectionCollapsible({ title, defaultOpen = true, children }: SectionCollapsibleProps) {
|
||||
const group = useSectionCollapsibleGroup();
|
||||
const [open, setOpen] = useState(group?.batchOpen ?? defaultOpen);
|
||||
const [seenVersion, setSeenVersion] = useState(group?.batchVersion ?? 0);
|
||||
|
||||
if (group && group.batchVersion !== seenVersion) {
|
||||
setSeenVersion(group.batchVersion);
|
||||
setOpen(group.batchOpen);
|
||||
}
|
||||
|
||||
const collapsibleProps = group ? { open, onOpenChange: setOpen } : { defaultOpen };
|
||||
|
||||
return (
|
||||
<Collapsible defaultOpen={defaultOpen} className="mx-4 rounded-sm border bg-background">
|
||||
<Collapsible {...collapsibleProps} className="mx-4 rounded-sm border bg-background">
|
||||
<CollapsibleTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Generated
+11
@@ -1217,6 +1217,9 @@ importers:
|
||||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.20
|
||||
decimal.js:
|
||||
specifier: ^10.6.0
|
||||
version: 10.6.0
|
||||
js-cookie:
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.5
|
||||
@@ -1511,6 +1514,9 @@ importers:
|
||||
'@radix-ui/react-slot':
|
||||
specifier: ^1.1.2
|
||||
version: 1.2.4(@types/react@19.2.14)(react@19.2.4)
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.21.2
|
||||
version: 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
axios:
|
||||
specifier: 1.8.1
|
||||
version: 1.8.1
|
||||
@@ -4886,6 +4892,9 @@ packages:
|
||||
decimal.js-light@2.5.1:
|
||||
resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==}
|
||||
|
||||
decimal.js@10.6.0:
|
||||
resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
|
||||
|
||||
deep-eql@5.0.2:
|
||||
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -10599,6 +10608,8 @@ snapshots:
|
||||
|
||||
decimal.js-light@2.5.1: {}
|
||||
|
||||
decimal.js@10.6.0: {}
|
||||
|
||||
deep-eql@5.0.2: {}
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
Reference in New Issue
Block a user