diff --git a/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx b/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx index 6915214d9..fbb1b0e43 100644 --- a/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx +++ b/apps/as/src/pages/design-cnstn/ui/design-view-page.tsx @@ -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,35 +81,40 @@ function DesignViewPage({ id }: DesignViewPageProps) { ); return ( -
- - - - - - - - +
+ + +
+ + + + + + + + +
+
); } diff --git a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx index 96f3124b3..bb7b22549 100644 --- a/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx +++ b/apps/as/src/pages/fnrs-cnsltn/ui/fnrs-view-page.tsx @@ -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,46 +95,51 @@ function FnrsViewPage({ id }: FnrsViewPageProps) { ); return ( -
- - - - - - - - - - - - +
+ + +
+ + + + + + + + + + + + +
+
); } diff --git a/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx b/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx index 6e5bd3eca..6a4f5ad2b 100644 --- a/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx +++ b/apps/as/src/pages/instl-sncn/ui/instl-view-page.tsx @@ -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,48 +93,53 @@ function InstlViewPage({ id }: InstlViewPageProps) { ); return ( -
- - - - - - - - - - - +
+ + +
+ + + + + + + + + + + +
+
); } diff --git a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx index 63b61052b..3099c4c37 100644 --- a/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx +++ b/apps/as/src/pages/sewer-bsc-plan/ui/sewer-bsc-plan-view-page.tsx @@ -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,48 +100,53 @@ function SewerBscPlanViewPage({ id, propChgCycl }: SewerBscPlanViewPageProps) { ); return ( -
- - - - - - - - - - - - - +
+ + +
+ + + + + + + + + + + + + +
+
); } diff --git a/apps/as/src/shared/ui/index.ts b/apps/as/src/shared/ui/index.ts index 577618146..813bcafd5 100644 --- a/apps/as/src/shared/ui/index.ts +++ b/apps/as/src/shared/ui/index.ts @@ -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"; diff --git a/apps/as/src/shared/ui/section-collapsible-group.tsx b/apps/as/src/shared/ui/section-collapsible-group.tsx new file mode 100644 index 000000000..88828e335 --- /dev/null +++ b/apps/as/src/shared/ui/section-collapsible-group.tsx @@ -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(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 ( + + {children} + + ); +} + +function SectionCollapsibleToggle() { + const group = useSectionCollapsibleGroup(); + + if (!group) return null; + + const { batchOpen, expandAll, collapseAll } = group; + + return ( +
+ + +
+ ); +} + +export { SectionCollapsibleGroup, SectionCollapsibleToggle, useSectionCollapsibleGroup }; diff --git a/apps/as/src/shared/ui/section-collapsible.tsx b/apps/as/src/shared/ui/section-collapsible.tsx index 2d9d6f27e..9b6fa050b 100644 --- a/apps/as/src/shared/ui/section-collapsible.tsx +++ b/apps/as/src/shared/ui/section-collapsible.tsx @@ -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 ( - +