fo: 테마적용1

This commit is contained in:
2026-06-25 14:34:55 +09:00
parent 793c673414
commit 76a634cf9a
24 changed files with 472 additions and 176 deletions
@@ -237,7 +237,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
onSelectValue={(val) => setFlowPanel(val.toString())}
className="mx-3 w-[150px]"
label=""
selectClass="w-full p-1 border rounded bg-white"
selectClass="w-full rounded border border-input bg-form p-1"
/>
</div>
</TableCell>
@@ -251,7 +251,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
mode="single"
selected={startDate}
onSelect={(date) => handleStartDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={startDate}
/>
@@ -262,7 +262,7 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
mode="single"
selected={endDate}
onSelect={(date) => handleEndDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={endDate}
/>
@@ -275,4 +275,4 @@ export default function FacilityTermModalHeader<T extends { msrDt: string }>({
</div>
</ListDiv>
);
}
}
@@ -219,7 +219,7 @@ export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }
return (
<ListDiv className="!h-[100px]">
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0r">
<div className="card !m-[1.2rem] max-h-[40rem] overflow-auto !p-0">
<Table>
<thead>
<TableRow>
@@ -237,7 +237,7 @@ export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }
onSelectValue={(val) => setFlowPanel(val.toString())}
className="mx-3 w-[150px]"
label=""
selectClass="w-full p-1 border rounded bg-white"
selectClass="w-full rounded border border-input bg-form p-1"
/>
</div>
</TableCell>
@@ -251,7 +251,7 @@ export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }
mode="single"
selected={startDate}
onSelect={(date) => handleStartDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
defaultMonth={startDate}
/>
</div>
@@ -261,7 +261,7 @@ export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }
mode="single"
selected={endDate}
onSelect={(date) => handleEndDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
defaultMonth={endDate}
/>
</div>
@@ -273,4 +273,4 @@ export default function FacilityTermModalHeaderMonth<T extends { msrDt: string }
</div>
</ListDiv>
);
}
}
@@ -5,55 +5,55 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
return (
layoutNum === 'A' ? (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
</>
) : layoutNum === 'R' ? (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'유역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'유역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
</>
) : (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'행정구역'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
@@ -99,22 +99,22 @@ export default function SearchInputText({label=undefined, setValue=()=>{}, sidoS
return (
<div className={'relative'} ref={wrapperRef}>
{label && <Label className="w-20 text-xl text-gray-600 justify-self-center">{label}</Label>}
{label && <Label className="w-20 justify-self-center text-xl text-label">{label}</Label>}
<input
type="text"
value={textValue}
onChange={handleInputChange}
onFocus={onInputFocus}
className="w-[200px] ml-6 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
className="ml-6 w-[200px] rounded-md border border-input bg-form px-3 py-2 text-foreground focus:outline-none focus:ring-2 focus:ring-ring"
placeholder={`${label}을(를) 입력하세요`}
/>
{isOpen && processFacilityList.length > 0 && (
<div className="absolute z-10 w-[300px] px-2 py-1 !mt-5 ml-20 bg-white border border-gray-300 rounded-md shadow-lg h-90 overflow-auto">
<div className="absolute z-10 ml-20 !mt-5 h-[90px] w-[300px] overflow-auto rounded-md border border-border bg-popover px-2 py-1 text-popover-foreground shadow-lg">
<div className="max-h-72">
{processFacilityList.map((item : facilityListProps, index : number) => (
<div
key={index}
className="w-full text-left pl-1 pr-10 py-2 hover:bg-gray-100 cursor-pointer overflow-auto"
className="w-full cursor-pointer overflow-auto py-2 pl-1 pr-10 text-left hover:bg-accent hover:text-accent-foreground"
onClick={() => handleSuggestionClick(item.bscFctCd, item.bscFctNm, Number(item.fctCpc), item.trtFrfNm, item.efflWqltStndrdNm)}
role="button"
tabIndex={0}
@@ -17,7 +17,7 @@ function UnderComment({commentStartPoint="☞", commentArray=[], divHeight="14"}
<div className={"mt-"+divHeight}>
{commentArray.map((item, index) => (
<React.Fragment key={"comment" + index}>
<span className="text-2xl font-bold text-gray-500">
<span className="text-2xl font-bold text-muted-foreground">
{commentStartPoint} {item}
</span>
<br/>
@@ -28,4 +28,4 @@ function UnderComment({commentStartPoint="☞", commentArray=[], divHeight="14"}
}
}
export default UnderComment;
export default UnderComment;
+7 -4
View File
@@ -127,15 +127,18 @@ const Map = () => {
}
const el = overlayContainerRef.current;
el.className =
"ol-custom-overlay shadow-xl rounded-2xl bg-white/95 backdrop-blur p-3 border border-gray-200 min-w-[220px] max-w-[350px] ";
"ol-custom-overlay shadow-xl rounded-2xl backdrop-blur p-3 min-w-[220px] max-w-[350px]";
el.style.backgroundColor = "color-mix(in srgb, var(--popover) 95%, transparent)";
el.style.color = "var(--popover-foreground)";
el.style.border = "1px solid var(--border)";
el.innerHTML = `
<div class="font-semibold text-lg text-gray-800 mb-2 text-center bg-green-400">${title}</div>
<table class="w-full text-base text-gray-800">
<div class="mb-2 rounded-md px-2 py-1 text-center text-lg font-semibold" style="background-color: var(--secondary); color: var(--secondary-foreground);">${title}</div>
<table class="w-full text-base" style="color: var(--foreground);">
${Object.entries(props)
.map(
([k, v]) => `
<tr>
<td class="py-1 pr-2 text-gray-500 whitespace-nowrap">${k}</td>
<td class="whitespace-nowrap py-1 pr-2" style="color: var(--muted-foreground);">${k}</td>
<td class="py-1 font-medium">${safe(v)}</td>
</tr>`
)
@@ -54,23 +54,23 @@ export default function DrainageEquipment({searchYear = '', fcltyList = []}: Dra
const HeadMakeColSpan = ({ upHeadList }: { upHeadList: TableUpperProps[] }) => {
return (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'part1' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
head.id === 'part2' ? <TableHead rowSpan={3} className='w-60' key={head.id}>구분</TableHead> :
head.id == 'nowSum' ? <TableHead rowSpan={2} colSpan={3} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'현재\n(기준년도)'}</TableHead> :
head.id == 'stepOneSum' ? <TableHead rowSpan={1} colSpan={12} key={head.id} style={{ whiteSpace: 'pre-line' }}>{'변경(금회계획)'}</TableHead> :
head.id == 'etc' ? <TableHead rowSpan={3} key={head.id}>비고</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'stepOneSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>1단계</TableHead> :
head.id === 'stepTwoSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>2단계</TableHead> :
head.id === 'stepThreeSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>3단계</TableHead> :
head.id === 'stepFourSum' ? <TableHead rowSpan={1} colSpan={3} key={head.id}>4단계</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
@@ -147,7 +147,7 @@ export default function DashBoardChartModal({item='', period='', title='',modalD
if (label) {
config[label] = {
label: label,
color : "hsl(var(--chart-1))"
color : "var(--chart-1)"
};
}
return config;
@@ -32,12 +32,12 @@ const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: s
return ( <>
<TableRow>{
upHeadList.map((head: TableUpperProps) =>
(!head.upSequnce?<TableHead rowSpan={2}key={head.id}>{head.title}</TableHead>:
head.upName === 'upChangeRe'&& head.upSequnce=== 1?<TableHead key={head.id} rowSpan={1} colSpan={7} style={{ whiteSpace: 'pre-line' }}>{'시설계획\n(금회)'}</TableHead>:null))}
(!head.upSequnce?<TableHead className="fo-facility-info-header-surface" rowSpan={2}key={head.id}>{head.title}</TableHead>:
head.upName === 'upChangeRe'&& head.upSequnce=== 1?<TableHead className="fo-facility-info-header-surface" key={head.id} rowSpan={1} colSpan={7} style={{ whiteSpace: 'pre-line' }}>{'시설계획\n(금회)'}</TableHead>:null))}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps, index: number) =>
(head.upName === 'upChangeRe'?<TableHead key={head.id} style={{ whiteSpace: 'pre-line' }}>{index===0?head.title:head.title+'\n('+planYearList[index-1]+')'}</TableHead>:null))}
(head.upName === 'upChangeRe'?<TableHead className="fo-facility-info-header-surface" key={head.id} style={{ whiteSpace: 'pre-line' }}>{index===0?head.title:head.title+'\n('+planYearList[index-1]+')'}</TableHead>:null))}
</TableRow>
</> )
}
@@ -52,20 +52,20 @@ const headMakeColSpanPlanFclty = (upHeadList: TableUpperProps[], planYearList: s
const headMakeColSpanOperationStatus = (upHeadList: TableUpperProps[], searchYear: string) => {
return ( <>
<TableRow>
<TableHead rowSpan={1} colSpan={17} style={{ whiteSpace: 'pre-line' }}>{searchYear+'년도 운영실태'}</TableHead>
<TableHead className="fo-facility-info-header-surface" rowSpan={1} colSpan={17} style={{ whiteSpace: 'pre-line' }}>{searchYear+'년도 운영실태'}</TableHead>
</TableRow>
<TableRow>{
upHeadList.map((head: TableUpperProps) =>
(head.upName === 'upChangeRe1'&&head.upSequnce===1?<TableHead key={head.id} rowSpan={2}colSpan={2} style={{ whiteSpace: 'pre-line' }}>{head.title}</TableHead>:
!head.upSequnce?<TableHead style={{ whiteSpace: 'pre-line' }} rowSpan={2}key={head.id}>{head.title}</TableHead>:
head.upName === 'upChangeRe2'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'연간 운영실태'}</TableHead>:
head.upName === 'upChangeRe3'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'하절기 운영실태\n(6~8월)'}</TableHead>:
head.upName === 'upChangeRe4'&&head.upSequnce===1?<TableHead key={head.id} colSpan={4} style={{ whiteSpace: 'pre-line' }}>{'동절기 운영실태\n(1~2월)'}</TableHead>:
head.upName === 'upChangeRe5'&&head.upSequnce===1?<TableHead key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'지하수 유입량 추정'}</TableHead>:null))}
(head.upName === 'upChangeRe1'&&head.upSequnce===1?<TableHead className="fo-facility-info-header-surface" key={head.id} rowSpan={2}colSpan={2} style={{ whiteSpace: 'pre-line' }}>{head.title}</TableHead>:
!head.upSequnce?<TableHead className="fo-facility-info-header-surface" style={{ whiteSpace: 'pre-line' }} rowSpan={2}key={head.id}>{head.title}</TableHead>:
head.upName === 'upChangeRe2'&&head.upSequnce===1?<TableHead className="fo-facility-info-header-surface" key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'연간 운영실태'}</TableHead>:
head.upName === 'upChangeRe3'&&head.upSequnce===1?<TableHead className="fo-facility-info-header-surface" key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'하절기 운영실태\n(6~8월)'}</TableHead>:
head.upName === 'upChangeRe4'&&head.upSequnce===1?<TableHead className="fo-facility-info-header-surface" key={head.id} colSpan={4} style={{ whiteSpace: 'pre-line' }}>{'동절기 운영실태\n(1~2월)'}</TableHead>:
head.upName === 'upChangeRe5'&&head.upSequnce===1?<TableHead className="fo-facility-info-header-surface" key={head.id} colSpan={3} style={{ whiteSpace: 'pre-line' }}>{'지하수 유입량 추정'}</TableHead>:null))}
</TableRow>
<TableRow>
{upHeadList.map((head: TableUpperProps) =>
(head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'||head.upName === 'upChangeRe4'||head.upName === 'upChangeRe5'?<TableHead style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
(head.upName === 'upChangeRe2'||head.upName === 'upChangeRe3'||head.upName === 'upChangeRe4'||head.upName === 'upChangeRe5'?<TableHead className="fo-facility-info-header-surface" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>:null))}
</TableRow>
</> )
}
@@ -226,7 +226,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
<LoadingOverlay isLoading={isLoadingPlanFclty} />
<div className="grid grid-cols-12 gap-1">
<div className="col-span-5">
<Table variant="default">
<Table variant="secondary">
<TableHeader>
{upChangeRePlanFclty}
</TableHeader>
@@ -239,18 +239,18 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
:((index === 6 || index === 7 || index === 8) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree' || head.id === 'stepFour'))?
null
:((index === 5) && (head.id === 'provisionalApproval' || head.id === 'stepTwo'))?
<TableCell colSpan={3} className="text-center border border-[var(--border)] bg-[rgb(141,141,148)] !text-[rgb(255,255,255)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
<TableCell colSpan={3} className="fo-facility-info-header-surface text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
:((index === 5) && (head.id === 'now' || head.id === 'stepOne' || head.id === 'stepThree'|| head.id === 'stepFour'))?
null
:(index < 5 || index > 5)&& (index!= 4) && (head.id ==='provisionalApproval'||head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour')
?<TableCell className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
:(head.id === "provisionalApproval" && index === 4)
?<TableCell colSpan={6} className="text-right border border-[var(--border)] text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{roundNumber(String((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3), 0)}</TableCell>
?<TableCell colSpan={6} className="text-right border border-border text-label" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{roundNumber(String((Number(waterUsage1)+Number(waterUsage2)+Number(waterUsage3))/3), 0)}</TableCell>
:((head.id ==='now'||head.id ==='stepOne'||head.id ==='stepTwo'||head.id ==='stepThree'||head.id ==='stepFour') )
?null
:(head.id === 'item' && index != 5)?
<TableCell className="text-center text-[rgb(100,119,132)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
:<TableCell className="text-center border border-[var(--border)] bg-[rgb(141,141,148)] !text-[rgb(255,255,255)]" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
<TableCell className="text-center text-label" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
:<TableCell className="fo-facility-info-header-surface text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>
))}
</TableRow>
))}
@@ -260,7 +260,7 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
<div className="col-span-7 h-[600px] overflow-x-auto">
<div className="w-[200%]">
<LoadingOverlay isLoading={isLoadingOperationStatus} />
<Table variant="default">
<Table variant="secondary">
<TableHeader>
{upChangeHeadListOperationStatus}
</TableHeader>
@@ -278,15 +278,15 @@ export default function ProcessFacilitySearch({searchYear = '', fcltyList = []}:
(head.id === 'rdiRain'&&index === 0)?<TableCell rowSpan={7} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el['rdiRain']}</TableCell>:
(head.id === 'rdiRain'&&index === 7)?<TableCell rowSpan={6} className="text-right" style={{ whiteSpace: 'pre-line' }} key={head.id+index}></TableCell>:
(head.id === 'waterQlty')?<TableCell className="text-center" style={{ whiteSpace: 'pre-line' }} key={head.id+index}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?<TableCell className="bg-green-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-50 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?<TableCell className="bg-yellow-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?<TableCell className="bg-green-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?<TableCell className="bg-blue-100 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?<TableCell className="bg-yellow-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?<TableCell className="bg-green-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?<TableCell className="bg-blue-200 text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=0 && index<=4))?<TableCell className="fo-facility-info-flow-year text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=5 && index<=10))?<TableCell className="fo-facility-info-water-year text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'yearAvg' || head.id === 'yearMax' || head.id === 'yearMin') && (index>=11 && index<=12))?<TableCell className="fo-facility-info-phosphorus-year text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'year', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=0 && index<=4))?<TableCell className="fo-facility-info-flow-summer text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=5 && index<=10))?<TableCell className="fo-facility-info-water-summer text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'summerAll' || head.id === 'summerThree' || head.id === 'summerRain') && (index>=11 && index<=12))?<TableCell className="fo-facility-info-phosphorus-summer text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'summer', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=0 && index<=4))?<TableCell className="fo-facility-info-flow-winter text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('flowRate', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=5 && index<=10))?<TableCell className="fo-facility-info-water-winter text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('waterQlty', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
((head.id === 'winterAll' || head.id === 'winterSunnyAvg' || head.id === 'winterSunnyMax' || head.id === 'winterSunnyMin') && (index>=11 && index<=12))?<TableCell className="fo-facility-info-phosphorus-winter text-right cursor-pointer" style={{ whiteSpace: 'pre-line' }} key={head.id+index} onClick={()=>{fncLoadModal('chongin', 'winter', el['waterQlty'] as string);}}>{el[head.id]}</TableCell>:
null
))}
</TableRow>
@@ -60,7 +60,14 @@ export default function DashBoardChart({searchYear = '', fcltyList = []}: facili
/**
* 차트 Config
*/
const colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#00b50c", "#D4A5A5"];
const colors = [
"var(--chart-5)",
"var(--chart-2)",
"var(--chart-1)",
"var(--chart-3)",
"var(--primary)",
"var(--chart-6)",
];
//유입하수량-강수량
const chartConfig_inflowRain = {
@@ -50,7 +50,7 @@ export default function RainManageTab({ searchYear = '', fcltyList = [] }: facil
widthFixed={true}
>
</UiTable>
<span className="text-2xl font-bold text-gray-500">☞ 일수에 강우영향일 포함됨</span>
<span className="text-2xl font-bold text-muted-foreground">☞ 일수에 강우영향일 포함됨</span>
</div>
)
}
@@ -198,7 +198,7 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
mode="single"
selected={startDate}
onSelect={(date) => handleStartDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={startDate}
/>
@@ -209,7 +209,7 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
mode="single"
selected={endDate}
onSelect={(date) => handleEndDateSelect(date as Date)}
className="w-full p-1 border rounded bg-white"
className="w-full rounded border border-input bg-form p-1 text-foreground"
disabled={(date) => !isDateInRanges(date)}
defaultMonth={endDate}
/>
@@ -239,4 +239,4 @@ export default function PrecipitationModal(props: PrecipitationModalProps) {
</ListDiv>
</>
);
}
}
@@ -17,27 +17,27 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
return (
layoutNum === 0 ? (
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
return <TableHead className="bg-secondary" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps, idx: number) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
if (idx == 1 || idx == 2 || idx == 3) {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
else {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
}
})}
@@ -45,27 +45,27 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
</>
) : layoutNum === 1 ? (
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
return <TableHead className="bg-secondary" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps, idx: number) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
if (idx == 1 || idx == 2 || idx == 3) {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
else {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
}
})}
@@ -73,29 +73,29 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
</>
) : layoutNum === 2 ? (
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
return <TableHead className="bg-secondary" colSpan={3} style={{ whiteSpace: 'pre-line' }} key={head.id}>권역</TableHead>
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
return <TableHead className="bg-secondary" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>행정구역</TableHead>
}else if(head.upName==="upChangeRe3"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
}else if(head.upName==="upChangeRe4"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유출</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps, idx: number) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4') {
if (idx == 1 || idx == 2 || idx == 3) {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
else {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
}
})}
@@ -103,25 +103,25 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
</>
) : layoutNum === 3 ? (
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe1"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
}else if(head.upName==="upChangeRe2"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
return <TableHead className="bg-secondary" colSpan={5} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps, idx: number) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
if (idx == 1 || idx == 2 || idx == 3) {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
else {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
}
})}
@@ -129,23 +129,23 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
</>
) : layoutNum === 4 ? (
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe"&&head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={4} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
return <TableHead className="bg-secondary" colSpan={4} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps, idx: number) => {
if (head.upName === 'upChangeRe') {
if (idx == 1 || idx == 2 || idx == 3) {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
else {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
}
})}
@@ -153,21 +153,21 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
</>
) : layoutNum === 5 ? ( // 총인설비 수질현황 헤더
<>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if(!head.upName) {
return <TableHead className="w-[180px] bg-gray-50" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
return <TableHead className="w-[180px] bg-secondary" rowSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead>
}else if(head.upName==="upChangeRe1" && head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
return <TableHead className="bg-secondary" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>유입</TableHead>
}else if(head.upName==="upChangeRe2" && head.upSequnce===1) {
return <TableHead className="bg-gray-50" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
return <TableHead className="bg-secondary" colSpan={2} style={{ whiteSpace: 'pre-line' }} key={head.id}>방류</TableHead>
}
})}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-1/8 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
@@ -237,7 +237,7 @@ export default function FlowRateModal(props: { fcltyName: string; facilityCd: st
const raw = row.infoRnDay;
const value = typeof raw === "string" ? Number(raw.replace(/,/g, "").trim()) : Number(raw);
if (!Number.isFinite(value)) return "";
return value > 3 ? "bg-slate-50" : "";
return value > 3 ? "fo-rain-impact-row" : "";
},
[activeTab],
);
@@ -5,77 +5,77 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
return (
layoutNum === 0 ? (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={2}>{'행정구역'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={19}>{'시설계획'}</TableHead> :
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={2}>{'행정구역'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={19}>{'시설계획'}</TableHead> :
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => (
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
null
))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
</>
) : layoutNum === 1 ? (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={3} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={3} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={3}>{'유역'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={3}>{'유역'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={2} colSpan={6}>{'증설계획'}</TableHead> :
!head.upName ? <TableHead rowSpan={3} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => (
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
head.upName === 'upChangeRe4' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
null
))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe' || head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' || head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
</>
) : (
<>
<TableRow className="bg-gray-50">{upHeadList.map((head: TableUpperProps) =>
<TableRow className="bg-secondary">{upHeadList.map((head: TableUpperProps) =>
(head.id === 'trtFrfNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id === 'laeNm' ? <TableHead className="w-1/12" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.id == 'fctCpc' || head.id == 'planInputWaterQlty' || head.id == 'designInputWaterQlty' ? <TableHead rowSpan={2} className="w-40" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> :
head.id === 'trstOprEtpNm' ? <TableHead className="w-1/15" rowSpan={2} key={head.id}>{head.title}</TableHead> :
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'환경청'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="w-75 bg-gray-50" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-gray-20" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
head.upName === 'upChangeRe1' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={3}>{'권역'}</TableHead> :
head.upName === 'upChangeRe2' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={2}>{'환경청'}</TableHead> :
head.upName === 'upChangeRe3' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'증설계획(m³/일)'}</TableHead> :
head.upName === 'upChangeRe5' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={6}>{'처리인구(인)'}</TableHead> :
head.upName === 'upChangeRe6' && head.upSequnce === 1 ? <TableHead className="w-75 bg-secondary" style={{ whiteSpace: 'pre-line' }} key={head.id} rowSpan={1} colSpan={7}>{'처리구역(k㎡)'}</TableHead> :
!head.upName ? <TableHead rowSpan={2} className="w-1/20 bg-accent text-accent-foreground" style={{ whiteSpace: 'pre-line' }} key={head.id}>{head.title}</TableHead> : null))}
</TableRow>
<TableRow className="bg-gray-50">
<TableRow className="bg-secondary">
{upHeadList.map((head: TableUpperProps) => {
if (head.upName === 'upChangeRe1' || head.upName === 'upChangeRe2' ||head.upName === 'upChangeRe3' || head.upName === 'upChangeRe4' || head.upName === 'upChangeRe5' || head.upName === 'upChangeRe6') {
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-gray-50">{head.title}</TableHead>;
return <TableHead key={head.id} style={{ whiteSpace: 'pre-line' }} className="w-40 bg-secondary">{head.title}</TableHead>;
}
})}
</TableRow>
@@ -84,4 +84,4 @@ const HeadMakeColSpan = ({ upHeadList, layoutNum }: { upHeadList: TableUpperProp
);
}
export { HeadMakeColSpan };
export { HeadMakeColSpan };
@@ -116,7 +116,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
<SelectBox
labelClass="w-[40px]"
className="mr-10 w-[200px]"
selectClass="rounded-lg bg-white"
selectClass="rounded-lg"
label="시도"
selectArray={sidoData}
onSelectValue={(val) => onSelectValue(val.toString(), "ctpvCd")}
@@ -125,7 +125,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
<SelectBox
labelClass="w-[65px]"
className="mr-10 w-[200px]"
selectClass="rounded-lg bg-white"
selectClass="rounded-lg"
label="시군구"
selectArray={filteredSigunData}
onSelectValue={(val) => onSelectValue(val.toString(), "sggCd")}
@@ -134,7 +134,7 @@ export function SearchBar({ onFeatureSelect, gisMaps }: SearchBarProps) {
<SelectBox
labelClass="w-[140px]"
className="mr-3 w-[250px]"
selectClass="rounded-lg bg-white"
selectClass="rounded-lg"
label="하수처리시설"
selectArray={facilityData}
onSelectValue={(val) => onSelectValue(val.toString(), "fcltCd")}
@@ -0,0 +1,164 @@
# apps/fo 테마 적용 작업계획
작성일: 2026-06-25
대상 앱: `D:\iipbs\frontend\apps\fo`
## 1. 목적
- `apps/fo` 프로그램 페이지 내부에 직접 박혀 있는 색상 하드코딩을 식별한다.
- 가능한 범위는 `packages/common/assets/src/styles/base.css`의 CSS 변수 영향권으로 옮긴다.
- 즉 `bg-white`, `text-gray-*`, `border-gray-*`, `bg-blue-*`, `bg-green-*`, `bg-red-*` 같은 직접 색상 표현을 `background`, `foreground`, `label`, `border`, `secondary`, `accent`, `primary`, `destructive` 계열 토큰으로 치환한다.
## 2. 전제
- `apps/fo`는 [tailwind.config.ts](D:/iipbs/frontend/apps/fo/tailwind.config.ts:1)에서 공통 preset을 사용한다.
- 공통 토큰은 [packages/common/assets/src/styles/base.css](D:/iipbs/frontend/packages/common/assets/src/styles/base.css:1)에 정의되어 있다.
- `packages/common/components`, `packages/common/assets`는 기준 레이어이며, 앱 작업은 이 기준을 따르는 방향으로 진행한다.
- 단, 이번 요청의 1차 목표는 `apps/fo` 내부 코드에 박혀 있는 색상을 줄이는 것이다.
## 3. 확인된 하드코딩 유형
현재 `apps/fo`에서 확인된 대표 패턴은 아래와 같다.
- 검색 입력/선택 UI
- `apps/fo/app/components/common/SearchInput.tsx`
- `apps/fo/app/pages/map/searchBar/searchBar.tsx`
- `apps/fo/app/components/common/FacilityTermModalHeader.tsx`
- `apps/fo/app/components/common/FacilityTermModalHeaderMonth.tsx`
- 대시보드/안내문구
- `apps/fo/app/components/common/UnderComment.tsx`
- `apps/fo/app/pages/(with-layout)/dashboard/rainManage/page.tsx`
- 대시보드 표 셀 상태색
- `apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx`
이 페이지는 특별한 페이지로, 연간, 하절기, 동절기 색을 구분하여 보여주어야 한다. 따라서 text-foreground 가 보이도록 하되 연간, 하절기, 동절기 색을 apps\fo\src\app\styles 아래 테마별 css에 정의해서 보여주어야 한다.
- 지도 오버레이/팝업
- `apps/fo/app/pages/(map-layout)/map/page.tsx`
- 테스트/샘플성 버튼
- `apps/fo/app/pages/(with-layout)/test/page.tsx`
- 모달 입력창
- `apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx`
## 4. 기본 원칙
### 4.1 바로 토큰 치환 가능한 경우
아래는 우선 토큰으로 바로 바꾼다.
- `bg-white` -> `bg-background` 또는 `bg-card` 또는 `bg-popover`
- `text-gray-900`, `text-gray-800` -> `text-foreground`
- `text-gray-700`, `text-gray-600` -> `text-label` 또는 `text-foreground`
- `text-gray-500` -> `text-muted-foreground` 또는 `text-placeholder`
- `border-gray-200`, `border-gray-300` -> `border-border`
- `focus:ring-blue-500` -> `focus:ring-ring`
- `text-blue-500`, `text-blue-600` -> `text-primary`
- `bg-blue-500`, `bg-blue-600` -> `bg-primary`
- `text-red-500`, `text-red-600` -> `text-destructive`
- `bg-red-50` 등 경고 계열 -> `bg-accent` 또는 별도 위험 상태 규칙 검토
### 4.2 바로 토큰 치환하면 안 되는 경우
아래는 의미색일 가능성이 높아 바로 토큰화하지 않는다.
- 범례 색상
- 데이터 구분용 heatmap/구간 색상
- 수질/계절/유형별 비교 색상
- 지도 오버레이에서 정보 카테고리 의미를 나타내는 색
이 경우는 다음 중 하나로 처리한다.
- 유지
- 별도 의미 클래스 부여
- 앱 전용 CSS로 상태 클래스를 만든 뒤 theme-safe surface만 토큰화
## 5. 우선순위
### 5.1 1순위: 일반 UI surface
가장 먼저 처리한다.
- 검색 입력창 배경/보더/텍스트
- 검색 결과 dropdown 배경/hover
- 팝업/모달 wrapper 배경/보더
- 제목/라벨/안내문구 색
- 버튼의 직접 blue/red/white 색상
이 영역은 theme 적용 체감이 가장 크고, 토큰 치환도 안전하다.
### 5.2 2순위: 테이블/리스트
- `selectedFcltList`
- `facilityInfo`
- modal 내부 표
- overlay 내 표 구조
이 영역은 `bg-secondary`, `bg-accent`, `text-secondary-foreground`, `border-border` 계열로 정리한다.
### 5.3 3순위: 의미색 데이터 표현
- `facilityInfo`의 계절/항목별 `bg-green-*`, `bg-blue-*`
- 지도 범례 색상
- 지도 feature overlay 강조색
- 대시보드 표 셀 상태색
- `apps/fo/app/pages/(with-layout)/dashboard/facilityInfo/page.tsx`
이 페이지는 특별한 페이지로, 연간, 하절기, 동절기 색을 구분하여 보여주어야 한다. 따라서 text-foreground 가 보이도록 하되 연간, 하절기, 동절기 색을 apps\fo\src\app\styles 아래 테마별 css에 정의해서 보여주어야 한다.
이 영역은 “없애는 것”보다 “역할을 분리하는 것”이 중요하다.
## 6. 실제 작업 순서
1. `apps/fo` 내부 하드코딩 색상 파일 목록 확정
2. 공통 UI와 데이터 의미색을 분리
3. 일반 UI 색상부터 `base.css` 토큰으로 치환
4. 필요 시 `apps/fo/app/styles/*.css`에 앱 전용 의미 클래스 추가
5. `dashboard`, `map`, `modal`, `search` 대표 화면 점검
6. 남은 의미색 영역은 별도 상태색 정책으로 정리
## 7. 권장 치환 전략
### 7.1 JSX 안에서 바로 치환
아래처럼 className을 직접 토큰 기반으로 변경한다.
- `bg-white` -> `bg-background`
- `text-gray-600` -> `text-label`
- `border-gray-300` -> `border-border`
이 방식은 빠르지만 반복이 많으면 유지보수성이 떨어진다.
### 7.2 반복되는 UI는 앱 전용 클래스 도입
예:
- `fo-search-panel`
- `fo-search-input`
- `fo-popup-card`
- `fo-empty-text`
반복되는 구조는 `apps/fo/app/styles/components*.css`에 올리고, JSX에서는 의미 클래스만 사용한다.
이 방식이 장기적으로 더 좋다.
## 8. 예상 주의사항
- `h-90` 같은 Tailwind v3 미지원 클래스가 섞여 있을 수 있다.
- `bg-white`를 `bg-background`로 바꾸면 black theme에서 contrast가 크게 달라질 수 있으므로 텍스트 색도 같이 바꿔야 한다.
- `bg-blue-*`, `bg-green-*`는 실제 status color인지 단순 강조색인지 구분하고 바꿔야 한다.
- 지도 오버레이는 HTML string으로 만드는 부분이 있으면 className 치환만으로 끝나지 않을 수 있다.
## 9. 1차 적용 추천 대상
우선 아래 파일부터 적용하는 것이 효율적이다.
1. `apps/fo/app/components/common/SearchInput.tsx`
2. `apps/fo/app/pages/map/searchBar/searchBar.tsx`
3. `apps/fo/app/components/common/UnderComment.tsx`
4. `apps/fo/app/pages/(with-layout)/dashboard/rainManage/page.tsx`
5. `apps/fo/app/components/common/FacilityTermModalHeader.tsx`
6. `apps/fo/app/components/common/FacilityTermModalHeaderMonth.tsx`
7. `apps/fo/app/pages/(with-layout)/facilityPrecipitation/modal/page.tsx`
## 10. 결론
- `apps/fo`도 `apps/wr`와 동일하게 `base.css` 토큰 중심으로 정리 가능하다.
- 1차는 일반 UI 하드코딩 제거에 집중하고, 데이터 의미색은 유지 또는 별도 정책으로 분리하는 것이 맞다.
- 가장 안전한 방향은 “반복 UI는 앱 전용 의미 클래스”, “일회성은 JSX에서 직접 토큰 치환”의 혼합 방식이다.
@@ -15,6 +15,20 @@
}
[data-theme="black"] {
--fo-facility-info-flow-year-bg: color-mix(in srgb, var(--chart-4) 20%, var(--secondary));
--fo-facility-info-water-year-bg: color-mix(in srgb, var(--chart-3) 20%, var(--secondary));
--fo-facility-info-phosphorus-year-bg: color-mix(in srgb, var(--chart-1) 20%, var(--secondary));
--fo-facility-info-flow-summer-bg: color-mix(in srgb, var(--chart-4) 28%, var(--secondary));
--fo-facility-info-water-summer-bg: color-mix(in srgb, var(--chart-3) 28%, var(--secondary));
--fo-facility-info-phosphorus-summer-bg: color-mix(in srgb, var(--chart-1) 28%, var(--secondary));
--fo-facility-info-flow-winter-bg: color-mix(in srgb, var(--chart-4) 36%, var(--secondary));
--fo-facility-info-water-winter-bg: color-mix(in srgb, var(--chart-3) 36%, var(--secondary));
--fo-facility-info-phosphorus-winter-bg: color-mix(in srgb, var(--chart-1) 36%, var(--secondary));
--fo-rain-impact-row-bg: color-mix(in srgb, var(--chart-1) 16%, var(--secondary));
--fo-facility-info-header-bg: #5e7b9c;
--fo-facility-info-header-fg: #ffffff;
--fo-facility-info-header-border: var(--border);
.card-border {
@apply border-[#3f4042] bg-[rgba(255,255,255,0.065)];
}
+15 -15
View File
@@ -15,6 +15,20 @@
}
[data-theme="blue"] {
--fo-facility-info-flow-year-bg: color-mix(in srgb, var(--chart-4) 16%, var(--background));
--fo-facility-info-water-year-bg: color-mix(in srgb, var(--chart-3) 16%, var(--background));
--fo-facility-info-phosphorus-year-bg: color-mix(in srgb, var(--chart-1) 16%, var(--background));
--fo-facility-info-flow-summer-bg: color-mix(in srgb, var(--chart-4) 24%, var(--background));
--fo-facility-info-water-summer-bg: color-mix(in srgb, var(--chart-3) 24%, var(--background));
--fo-facility-info-phosphorus-summer-bg: color-mix(in srgb, var(--chart-1) 24%, var(--background));
--fo-facility-info-flow-winter-bg: color-mix(in srgb, var(--chart-4) 32%, var(--background));
--fo-facility-info-water-winter-bg: color-mix(in srgb, var(--chart-3) 32%, var(--background));
--fo-facility-info-phosphorus-winter-bg: color-mix(in srgb, var(--chart-1) 32%, var(--background));
--fo-rain-impact-row-bg: color-mix(in srgb, var(--chart-1) 12%, var(--background));
--fo-facility-info-header-bg: #eaf3fb;
--fo-facility-info-header-fg: #647784;
--fo-facility-info-header-border: #e5e5e5;
.card-border {
@apply border-[#d8e3eb] bg-white shadow-blur;
}
@@ -44,23 +58,9 @@
@apply text-[#666666];
}
.table-ui.secondary {
@apply bg-white;
border-collapse: collapse;
}
.table-ui.secondary th {
@apply border-[#e5e5e5] bg-[#5987bf] text-[#ffffff];
font-weight: 500;
}
.table-ui.secondary td {
@apply border-[#e5e5e5] bg-white text-[#666666];
}
.table-ui.secondary tbody tr:hover td {
@apply bg-[#f7fbff];
}
nav[aria-label="pagination"] li a {
border-color: transparent !important;
@@ -15,6 +15,20 @@
}
[data-theme="green"] {
--fo-facility-info-flow-year-bg: color-mix(in srgb, var(--chart-4) 15%, var(--background));
--fo-facility-info-water-year-bg: color-mix(in srgb, var(--chart-3) 15%, var(--background));
--fo-facility-info-phosphorus-year-bg: color-mix(in srgb, var(--chart-1) 15%, var(--background));
--fo-facility-info-flow-summer-bg: color-mix(in srgb, var(--chart-4) 23%, var(--background));
--fo-facility-info-water-summer-bg: color-mix(in srgb, var(--chart-3) 23%, var(--background));
--fo-facility-info-phosphorus-summer-bg: color-mix(in srgb, var(--chart-1) 23%, var(--background));
--fo-facility-info-flow-winter-bg: color-mix(in srgb, var(--chart-4) 31%, var(--background));
--fo-facility-info-water-winter-bg: color-mix(in srgb, var(--chart-3) 31%, var(--background));
--fo-facility-info-phosphorus-winter-bg: color-mix(in srgb, var(--chart-1) 31%, var(--background));
--fo-rain-impact-row-bg: color-mix(in srgb, var(--chart-3) 12%, var(--background));
--fo-facility-info-header-bg: #ebf7f7;
--fo-facility-info-header-fg: #64908f;
--fo-facility-info-header-border: var(--border);
.card-border {
@apply border-[#3f4042] bg-[rgba(255,255,255,0.065)];
}
+13 -6
View File
@@ -15,12 +15,19 @@
}
[data-theme="red"] {
/* .card-border {
@apply border-[#3f4042] bg-[rgba(255,255,255,0.065)];
}
.card-header {
@apply border-b-[#3f4042];
} */
--fo-facility-info-flow-year-bg: color-mix(in srgb, var(--chart-4) 14%, var(--background));
--fo-facility-info-water-year-bg: color-mix(in srgb, var(--chart-3) 14%, var(--background));
--fo-facility-info-phosphorus-year-bg: color-mix(in srgb, var(--chart-1) 14%, var(--background));
--fo-facility-info-flow-summer-bg: color-mix(in srgb, var(--chart-4) 22%, var(--background));
--fo-facility-info-water-summer-bg: color-mix(in srgb, var(--chart-3) 22%, var(--background));
--fo-facility-info-phosphorus-summer-bg: color-mix(in srgb, var(--chart-1) 22%, var(--background));
--fo-facility-info-flow-winter-bg: color-mix(in srgb, var(--chart-4) 30%, var(--background));
--fo-facility-info-water-winter-bg: color-mix(in srgb, var(--chart-3) 30%, var(--background));
--fo-facility-info-phosphorus-winter-bg: color-mix(in srgb, var(--chart-1) 30%, var(--background));
--fo-rain-impact-row-bg: color-mix(in srgb, var(--destructive) 12%, var(--background));
--fo-facility-info-header-bg: #f6f6f9;
--fo-facility-info-header-fg: #808080;
--fo-facility-info-header-border: var(--border);
}
input[type="file"] {
+75
View File
@@ -1,6 +1,22 @@
@tailwind components;
@layer components {
:root {
--fo-facility-info-flow-year-bg: color-mix(in srgb, var(--chart-4) 18%, var(--background));
--fo-facility-info-water-year-bg: color-mix(in srgb, var(--chart-3) 18%, var(--background));
--fo-facility-info-phosphorus-year-bg: color-mix(in srgb, var(--chart-1) 18%, var(--background));
--fo-facility-info-flow-summer-bg: color-mix(in srgb, var(--chart-4) 28%, var(--background));
--fo-facility-info-water-summer-bg: color-mix(in srgb, var(--chart-3) 28%, var(--background));
--fo-facility-info-phosphorus-summer-bg: color-mix(in srgb, var(--chart-1) 28%, var(--background));
--fo-facility-info-flow-winter-bg: color-mix(in srgb, var(--chart-4) 38%, var(--background));
--fo-facility-info-water-winter-bg: color-mix(in srgb, var(--chart-3) 38%, var(--background));
--fo-facility-info-phosphorus-winter-bg: color-mix(in srgb, var(--chart-1) 38%, var(--background));
--fo-rain-impact-row-bg: color-mix(in srgb, var(--chart-1) 10%, var(--background));
--fo-facility-info-header-bg: #eaf3fb;
--fo-facility-info-header-fg: #647784;
--fo-facility-info-header-border: var(--border);
}
.card {
@apply relative m-[0.6rem] box-border min-h-[2rem] rounded-[0.5rem] p-[0.6rem] text-[1.3rem] text-[#666];
}
@@ -14,6 +30,65 @@
@apply -mx-[0.6rem] mt-2 flex items-center justify-center border-t border-t-[#e1e7eb] py-4;
}
.fo-facility-info-flow-year,
.fo-facility-info-water-year,
.fo-facility-info-phosphorus-year,
.fo-facility-info-flow-summer,
.fo-facility-info-water-summer,
.fo-facility-info-phosphorus-summer,
.fo-facility-info-flow-winter,
.fo-facility-info-water-winter,
.fo-facility-info-phosphorus-winter {
color: var(--foreground);
}
.fo-facility-info-flow-year {
background-color: var(--fo-facility-info-flow-year-bg);
}
.fo-facility-info-water-year {
background-color: var(--fo-facility-info-water-year-bg);
}
.fo-facility-info-phosphorus-year {
background-color: var(--fo-facility-info-phosphorus-year-bg);
}
.fo-facility-info-flow-summer {
background-color: var(--fo-facility-info-flow-summer-bg);
}
.fo-facility-info-water-summer {
background-color: var(--fo-facility-info-water-summer-bg);
}
.fo-facility-info-phosphorus-summer {
background-color: var(--fo-facility-info-phosphorus-summer-bg);
}
.fo-facility-info-flow-winter {
background-color: var(--fo-facility-info-flow-winter-bg);
}
.fo-facility-info-water-winter {
background-color: var(--fo-facility-info-water-winter-bg);
}
.fo-facility-info-phosphorus-winter {
background-color: var(--fo-facility-info-phosphorus-winter-bg);
}
.fo-rain-impact-row td {
background-color: var(--fo-rain-impact-row-bg);
}
.fo-facility-info-header-surface {
border: 1px solid var(--fo-facility-info-header-border);
background-color: var(--fo-facility-info-header-bg);
color: var(--fo-facility-info-header-fg);
}
input[type="file"] {
@apply w-[200px] h-[40px] px-3 py-2 border border-[#d1d5db] rounded-md bg-white text-sm cursor-pointer;
}
@@ -14,25 +14,37 @@ interface UITabProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "dir"> {
tabList: TabItem[];
children?: React.ReactNode;
onValueChange?: (value: string) => void;
variant?: "default" | "underline" | "outline";
}
const UITab = React.forwardRef<HTMLDivElement, UITabProps>(
({ defaultValue, tabList, children, onValueChange, className, ...props }, ref) => {
(
{
defaultValue,
tabList,
children,
onValueChange,
className,
variant = "default",
...props
},
ref,
) => {
return (
<Tabs
variant="underline"
variant={variant}
defaultValue={defaultValue || tabList[0]?.value}
className={cn("btab_root", className)}
className={cn("w-full", variant === "underline" && "btab_root", className)}
onValueChange={onValueChange}
ref={ref}
{...props}
>
<TabsList className="btab_list">
<TabsList className={cn(variant === "underline" && "btab_list")}>
{tabList.map((tab) => (
<TabsTrigger
key={tab.value}
value={tab.value}
className="btab_trigger"
className={cn(variant === "underline" && "btab_trigger")}
>
{tab.label}
</TabsTrigger>