[as] chore: 행정지원 메뉴 수정
This commit is contained in:
@@ -6,6 +6,7 @@ import { Paperclip } from "lucide-react";
|
|||||||
|
|
||||||
import { PROXY_HOST } from "@/shared/config";
|
import { PROXY_HOST } from "@/shared/config";
|
||||||
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import type { DesignCnstnRvwOpnnResponseDto } from "@/entities/design-cnstn";
|
import type { DesignCnstnRvwOpnnResponseDto } from "@/entities/design-cnstn";
|
||||||
@@ -240,7 +241,9 @@ const TechReviewOpinionSection = forwardRef<
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{uploadedFile ? (
|
{uploadedFile ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xl">{uploadedFile.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{uploadedFile.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -46,12 +46,7 @@ function ChecklistTaskPanel({
|
|||||||
.forEach((row) => {
|
.forEach((row) => {
|
||||||
nextResults[buildChecklistRowKey(row, selectedReviewStep)] = value;
|
nextResults[buildChecklistRowKey(row, selectedReviewStep)] = value;
|
||||||
});
|
});
|
||||||
return patchChecklistFormState(
|
return patchChecklistFormState(prev, { results: nextResults }, allRows, selectedReviewStep);
|
||||||
prev,
|
|
||||||
{ results: nextResults },
|
|
||||||
allRows,
|
|
||||||
selectedReviewStep,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +72,7 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="white"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("Y")}
|
onClick={() => handleSelectAll("Y")}
|
||||||
>
|
>
|
||||||
@@ -87,9 +83,9 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="gray"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("N")}
|
onClick={() => handleSelectAll("N")}
|
||||||
className="!bg-destructive"
|
|
||||||
>
|
>
|
||||||
전체 아니오
|
전체 아니오
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Paperclip } from "lucide-react";
|
|||||||
|
|
||||||
import { PROXY_HOST } from "@/shared/config";
|
import { PROXY_HOST } from "@/shared/config";
|
||||||
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import type { FnrsCnsltnRvwOpnnResponseDto } from "@/entities/fnrs-cnsltn";
|
import type { FnrsCnsltnRvwOpnnResponseDto } from "@/entities/fnrs-cnsltn";
|
||||||
@@ -247,7 +248,9 @@ const TechReviewOpinionSection = forwardRef<
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{uploadedFile ? (
|
{uploadedFile ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xl">{uploadedFile.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{uploadedFile.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -45,12 +45,7 @@ function ChecklistTaskPanel({
|
|||||||
.forEach((row) => {
|
.forEach((row) => {
|
||||||
nextResults[buildChecklistRowKey(row, selectedReviewStep)] = value;
|
nextResults[buildChecklistRowKey(row, selectedReviewStep)] = value;
|
||||||
});
|
});
|
||||||
return patchChecklistFormState(
|
return patchChecklistFormState(prev, { results: nextResults }, allRows, selectedReviewStep);
|
||||||
prev,
|
|
||||||
{ results: nextResults },
|
|
||||||
allRows,
|
|
||||||
selectedReviewStep,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +71,7 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="white"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("Y")}
|
onClick={() => handleSelectAll("Y")}
|
||||||
>
|
>
|
||||||
@@ -86,9 +82,9 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="gray"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("N")}
|
onClick={() => handleSelectAll("N")}
|
||||||
className="!bg-destructive"
|
|
||||||
>
|
>
|
||||||
전체 아니오
|
전체 아니오
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Paperclip } from "lucide-react";
|
|||||||
|
|
||||||
import { PROXY_HOST } from "@/shared/config";
|
import { PROXY_HOST } from "@/shared/config";
|
||||||
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import type { InstlSncnRvwOpnnResponseDto, ReviewStepCode } from "@/entities/instl-sncn";
|
import type { InstlSncnRvwOpnnResponseDto, ReviewStepCode } from "@/entities/instl-sncn";
|
||||||
@@ -240,7 +241,9 @@ const TechReviewOpinionSection = forwardRef<
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{uploadedFile ? (
|
{uploadedFile ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xl">{uploadedFile.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{uploadedFile.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -49,23 +49,12 @@ export const REVIEW_STEP_LABELS: Record<ReviewStepCode, string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const TASK_CODE_LABELS: Record<string, string> = {
|
export const TASK_CODE_LABELS: Record<string, string> = {
|
||||||
RE: "재이용수",
|
CP: "부분변경",
|
||||||
SP: "하수관로",
|
AP: "전체변경",
|
||||||
SF: "하수처리시설",
|
MP: "병합",
|
||||||
MP: "변경",
|
|
||||||
CP: "신규",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PBADMS_PROGRESS_ORDER = [
|
export const PBADMS_PROGRESS_ORDER = ["SV", "SL", "TA", "EP", "LE", "TP", "ER", "TE"] as const;
|
||||||
"SV",
|
|
||||||
"SL",
|
|
||||||
"TA",
|
|
||||||
"EP",
|
|
||||||
"LE",
|
|
||||||
"TP",
|
|
||||||
"ER",
|
|
||||||
"TE",
|
|
||||||
] as const;
|
|
||||||
|
|
||||||
export const ROLE_TO_REVIEW_STEP: Record<string, ReviewStepCode> = {
|
export const ROLE_TO_REVIEW_STEP: Record<string, ReviewStepCode> = {
|
||||||
ROLE_USER05: "LOCAL",
|
ROLE_USER05: "LOCAL",
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="white"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("Y")}
|
onClick={() => handleSelectAll("Y")}
|
||||||
>
|
>
|
||||||
@@ -81,9 +82,9 @@ function ChecklistTaskPanel({
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="gray"
|
||||||
disabled={!isStepEditable}
|
disabled={!isStepEditable}
|
||||||
onClick={() => handleSelectAll("N")}
|
onClick={() => handleSelectAll("N")}
|
||||||
className="!bg-destructive"
|
|
||||||
>
|
>
|
||||||
전체 아니오
|
전체 아니오
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Paperclip } from "lucide-react";
|
|||||||
|
|
||||||
import { PROXY_HOST } from "@/shared/config";
|
import { PROXY_HOST } from "@/shared/config";
|
||||||
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
import { Field, FieldLabel, FieldSet } from "@/shared/ui/field";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import type { SewerBscPlanRvwOpnnResponseDto } from "@/entities/sewer-bsc-plan";
|
import type { SewerBscPlanRvwOpnnResponseDto } from "@/entities/sewer-bsc-plan";
|
||||||
@@ -247,7 +248,9 @@ const TechReviewOpinionSection = forwardRef<
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{uploadedFile ? (
|
{uploadedFile ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xl">{uploadedFile.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{uploadedFile.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Controller, useFieldArray, useFormContext, useWatch } from "react-hook-
|
|||||||
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
import { useConfirm } from "@frontend-opensource/use-react-hooks";
|
||||||
|
|
||||||
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field } from "@/shared/ui/field";
|
import { Field } from "@/shared/ui/field";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import { useFacilityList } from "@/entities/bns-if";
|
import { useFacilityList } from "@/entities/bns-if";
|
||||||
@@ -319,7 +320,9 @@ function TmplntFacilityAttachments({
|
|||||||
<TableCell>
|
<TableCell>
|
||||||
{hasFile ? (
|
{hasFile ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="text-xl">{displayFileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{displayFileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="icon"
|
size="icon"
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
import { Button, Dialog, DialogClose, DialogContent, DialogFooter } from "@common/components";
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogFooter,
|
|
||||||
} from "@common/components";
|
|
||||||
|
|
||||||
import { useAlertStore } from "../lib/use-alert-store";
|
import { useAlertStore } from "../lib/use-alert-store";
|
||||||
|
|
||||||
@@ -20,7 +14,7 @@ function AlertDialog() {
|
|||||||
<Dialog open={!!message} onOpenChange={handleOpenChange}>
|
<Dialog open={!!message} onOpenChange={handleOpenChange}>
|
||||||
<DialogContent aria-describedby={undefined}>
|
<DialogContent aria-describedby={undefined}>
|
||||||
<div className="py-10">
|
<div className="py-10">
|
||||||
<p className="text-foreground whitespace-pre-line text-center text-[1.4rem]">
|
<p className="whitespace-pre-line break-keep text-center text-[1.4rem] text-foreground">
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
export { PageLayout } from "./page-layout";
|
|
||||||
export { NoData } from "./no-data";
|
export { NoData } from "./no-data";
|
||||||
|
export { PageLayout } from "./page-layout";
|
||||||
|
export type { TextShimmerProps } from "./text-shimmer";
|
||||||
|
export { TEXT_SHIMMER_CLASS, TextShimmer } from "./text-shimmer";
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { cn } from "@common/components";
|
||||||
|
|
||||||
|
const TEXT_SHIMMER_CLASS =
|
||||||
|
"animate-text-shimmer bg-gradient-to-r from-muted-foreground via-muted to-muted-foreground bg-[length:200%_100%] bg-clip-text text-transparent";
|
||||||
|
|
||||||
|
interface TextShimmerProps extends React.ComponentPropsWithoutRef<"span"> {
|
||||||
|
active?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function TextShimmer({ active = false, className, children, ...props }: TextShimmerProps) {
|
||||||
|
return (
|
||||||
|
<span className={cn(className, active && TEXT_SHIMMER_CLASS)} {...props}>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { TEXT_SHIMMER_CLASS, TextShimmer };
|
||||||
|
export type { TextShimmerProps };
|
||||||
@@ -8,6 +8,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
|||||||
import { ENDPOINT } from "@/shared/config";
|
import { ENDPOINT } from "@/shared/config";
|
||||||
import { useTus } from "@/shared/lib";
|
import { useTus } from "@/shared/lib";
|
||||||
import type { AtflMngClientResponseDto, EsntlAtchFileMngTreeResponseDto } from "@/shared/model";
|
import type { AtflMngClientResponseDto, EsntlAtchFileMngTreeResponseDto } from "@/shared/model";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import { useEsntlAtchFileMngTree } from "@/entities/esntl";
|
import { useEsntlAtchFileMngTree } from "@/entities/esntl";
|
||||||
import {
|
import {
|
||||||
@@ -413,20 +414,21 @@ function AttachmentsFormSection({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={item.fileKey} className="flex items-center gap-2">
|
<div key={item.fileKey} className="flex items-center gap-2">
|
||||||
<span className="text-xl">
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
{item.file?.name ?? item.fileName}
|
{item.file?.name ?? item.fileName}
|
||||||
</span>
|
</TextShimmer>
|
||||||
<Button
|
{!uploading && (
|
||||||
size="icon"
|
<Button
|
||||||
onClick={(e) => {
|
size="icon"
|
||||||
e.preventDefault();
|
onClick={(e) => {
|
||||||
void removeEssentialFile(file.esntlAtchFileId, idx);
|
e.preventDefault();
|
||||||
}}
|
void removeEssentialFile(file.esntlAtchFileId, idx);
|
||||||
disabled={uploading}
|
}}
|
||||||
className="size-8 !bg-destructive"
|
className="size-8 !bg-destructive"
|
||||||
>
|
>
|
||||||
<i className="diveicon di-x text-xs" aria-label="삭제" />
|
<i className="diveicon di-x text-xs" aria-label="삭제" />
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -489,7 +491,9 @@ function AttachmentsFormSection({
|
|||||||
key={item.fileKey}
|
key={item.fileKey}
|
||||||
className="flex items-center justify-between rounded-sm border p-2"
|
className="flex items-center justify-between rounded-sm border p-2"
|
||||||
>
|
>
|
||||||
<span className="px-2 text-xl">{item.file?.name ?? item.fileName}</span>
|
<TextShimmer className="px-2 text-xl" active={uploading}>
|
||||||
|
{item.file?.name ?? item.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
color="gray"
|
color="gray"
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ import {
|
|||||||
TabsTrigger,
|
TabsTrigger,
|
||||||
} from "@common/components";
|
} from "@common/components";
|
||||||
|
|
||||||
import { buildChecklistTabs, normalizeTaskSeComCdArray, syncCklstResultListFromTree } from "../lib/checklist-form-utils";
|
import {
|
||||||
|
buildChecklistTabs,
|
||||||
|
normalizeTaskSeComCdArray,
|
||||||
|
syncCklstResultListFromTree,
|
||||||
|
} from "../lib/checklist-form-utils";
|
||||||
|
|
||||||
import { SectionCollapsible } from "./section-collapsible";
|
import { SectionCollapsible } from "./section-collapsible";
|
||||||
|
|
||||||
@@ -49,10 +53,7 @@ function ChecklistFormSection({ docSeComCd, fieldPrefix }: ChecklistFormSectionP
|
|||||||
const { watch, setValue, control, getValues } = useFormContext();
|
const { watch, setValue, control, getValues } = useFormContext();
|
||||||
const [activeTab, setActiveTab] = useState("");
|
const [activeTab, setActiveTab] = useState("");
|
||||||
const taskSeComCd = watch(`${fieldPrefix}.taskSeComCd`) as string | string[] | undefined;
|
const taskSeComCd = watch(`${fieldPrefix}.taskSeComCd`) as string | string[] | undefined;
|
||||||
const taskSeComCdArray = useMemo(
|
const taskSeComCdArray = useMemo(() => normalizeTaskSeComCdArray(taskSeComCd), [taskSeComCd]);
|
||||||
() => normalizeTaskSeComCdArray(taskSeComCd),
|
|
||||||
[taskSeComCd],
|
|
||||||
);
|
|
||||||
const cklstResultList =
|
const cklstResultList =
|
||||||
(useWatch({ control, name: "cklstResultList" }) as CklstResultListItem[] | undefined) ?? [];
|
(useWatch({ control, name: "cklstResultList" }) as CklstResultListItem[] | undefined) ?? [];
|
||||||
|
|
||||||
@@ -206,6 +207,7 @@ function ChecklistFormSection({ docSeComCd, fieldPrefix }: ChecklistFormSectionP
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="white"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleSelectAll(tab.code, "Y");
|
handleSelectAll(tab.code, "Y");
|
||||||
@@ -218,11 +220,11 @@ function ChecklistFormSection({ docSeComCd, fieldPrefix }: ChecklistFormSectionP
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
color="gray"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
handleSelectAll(tab.code, "N");
|
handleSelectAll(tab.code, "N");
|
||||||
}}
|
}}
|
||||||
className="!bg-destructive"
|
|
||||||
>
|
>
|
||||||
전체 아니오
|
전체 아니오
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from "react";
|
|||||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||||
|
|
||||||
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { Field } from "@/shared/ui/field";
|
import { Field } from "@/shared/ui/field";
|
||||||
import { useAcntgSeMngTree } from "@/entities/acntg";
|
import { useAcntgSeMngTree } from "@/entities/acntg";
|
||||||
import type { AtflMngClientResponseDto } from "@/entities/fnrs-cnsltn";
|
import type { AtflMngClientResponseDto } from "@/entities/fnrs-cnsltn";
|
||||||
@@ -257,12 +258,18 @@ function FnrsSharFormSection({ initialSharTree, initialSharAtchFiles }: FnrsShar
|
|||||||
<div className="mt-6 px-2 pb-2">
|
<div className="mt-6 px-2 pb-2">
|
||||||
<h3 className="mb-2 text-xl font-semibold">첨부파일</h3>
|
<h3 className="mb-2 text-xl font-semibold">첨부파일</h3>
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
<Input
|
{isSharUploading && uploadedFileName ? (
|
||||||
value={uploadedFileName}
|
<TextShimmer className="max-w-lg text-xl" active>
|
||||||
readOnly
|
{uploadedFileName}
|
||||||
placeholder="총사업비 신청서(.hwp) 파일을 등록해주세요."
|
</TextShimmer>
|
||||||
className="max-w-lg rounded-sm"
|
) : (
|
||||||
/>
|
<Input
|
||||||
|
value={uploadedFileName}
|
||||||
|
readOnly
|
||||||
|
placeholder="총사업비 신청서(.hwp) 파일을 등록해주세요."
|
||||||
|
className="max-w-lg rounded-sm"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Button type="button" color="white" disabled={isSharUploading} asChild>
|
<Button type="button" color="white" disabled={isSharUploading} asChild>
|
||||||
<label className="cursor-pointer">
|
<label className="cursor-pointer">
|
||||||
첨부파일
|
첨부파일
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import { useEffect, useId, useState } from "react";
|
import { useEffect, useId, useState } from "react";
|
||||||
|
|
||||||
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
import { getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { attachService } from "@/entities/attach";
|
import { attachService } from "@/entities/attach";
|
||||||
import { CodeSelect } from "@/entities/code";
|
import { CodeSelect } from "@/entities/code";
|
||||||
import {
|
import {
|
||||||
@@ -269,7 +270,9 @@ function SplmntDmndDialog({
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{row.uploadedFile ? (
|
{row.uploadedFile ? (
|
||||||
<div className="flex items-stretch gap-2">
|
<div className="flex items-stretch gap-2">
|
||||||
<span className="text-xl">{row.uploadedFile.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{row.uploadedFile.fileName}
|
||||||
|
</TextShimmer>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
size="icon"
|
size="icon"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Controller, useFormContext, useWatch } from "react-hook-form";
|
|||||||
import { Paperclip } from "lucide-react";
|
import { Paperclip } from "lucide-react";
|
||||||
|
|
||||||
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
import { dayjs, getDefaultFileKey, useTus } from "@/shared/lib";
|
||||||
|
import { TextShimmer } from "@/shared/ui";
|
||||||
import { attachService, useDownloadAttachmentByAtflCd } from "@/entities/attach";
|
import { attachService, useDownloadAttachmentByAtflCd } from "@/entities/attach";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
@@ -272,7 +273,9 @@ function SplmntDmndFormSection({ readOnly = false }: SplmntDmndFormSectionProps)
|
|||||||
{uploaded.fileName}
|
{uploaded.fileName}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-xl">{uploaded.fileName}</span>
|
<TextShimmer className="text-xl" active={uploading}>
|
||||||
|
{uploaded.fileName}
|
||||||
|
</TextShimmer>
|
||||||
)}
|
)}
|
||||||
{!isRowReadOnly ? (
|
{!isRowReadOnly ? (
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -83,12 +83,17 @@ export default {
|
|||||||
from: { transform: "translate(0,0) rotate(0deg)" },
|
from: { transform: "translate(0,0) rotate(0deg)" },
|
||||||
to: { transform: "translate(0,0) rotate(360deg)" },
|
to: { transform: "translate(0,0) rotate(360deg)" },
|
||||||
},
|
},
|
||||||
|
"text-shimmer": {
|
||||||
|
"0%": { backgroundPosition: "200% center" },
|
||||||
|
"100%": { backgroundPosition: "-200% center" },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
animation: {
|
animation: {
|
||||||
"accordion-down": "accordion-down 0.2s ease-out",
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
"accordion-up": "accordion-up 0.2s ease-out",
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
"spin-parent": "spin-parent 6s linear infinite",
|
"spin-parent": "spin-parent 6s linear infinite",
|
||||||
"spin-child": "spin-child 1s ease-in-out infinite",
|
"spin-child": "spin-child 1s ease-in-out infinite",
|
||||||
|
"text-shimmer": "text-shimmer 1.5s linear infinite",
|
||||||
},
|
},
|
||||||
backgroundImage: {
|
backgroundImage: {
|
||||||
"gradient-blue": "linear-gradient(.25turn, #2094fa, #00e5dd)",
|
"gradient-blue": "linear-gradient(.25turn, #2094fa, #00e5dd)",
|
||||||
|
|||||||
Reference in New Issue
Block a user