ui: 月度办理社保公积金区域改为可折叠卡片,添加统计摘要
This commit is contained in:
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'
|
|||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams } from 'react-router-dom'
|
||||||
import { toast } from 'sonner'
|
import { toast } from 'sonner'
|
||||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||||
import { Calculator, Check, Plus, Download, AlertCircle, Clock } from 'lucide-react'
|
import { Calculator, Check, Plus, Download, AlertCircle, Clock, ChevronDown, ChevronRight, Shield, Home } from 'lucide-react'
|
||||||
import { InlineAlert } from '../components/ui/InlineAlert'
|
import { InlineAlert } from '../components/ui/InlineAlert'
|
||||||
import PageGuide from '../components/ui/PageGuide'
|
import PageGuide from '../components/ui/PageGuide'
|
||||||
import { socialInsuranceApi, socialAccountApi } from '../lib/api-services'
|
import { socialInsuranceApi, socialAccountApi } from '../lib/api-services'
|
||||||
@@ -460,14 +460,40 @@ export default function SocialInsurance() {
|
|||||||
const sTable = renderSocialTable(city)
|
const sTable = renderSocialTable(city)
|
||||||
const hTable = renderHousingTable(city)
|
const hTable = renderHousingTable(city)
|
||||||
if (!sTable && !hTable) return null
|
if (!sTable && !hTable) return null
|
||||||
|
const sAddCity = sAdd.filter((i: any) => i.city === city)
|
||||||
|
const sSubCity = sSub.filter((i: any) => i.city === city)
|
||||||
|
const sNormalCity = sNormal.filter((i: any) => i.city === city)
|
||||||
|
const hAddCity = hAdd.filter((i: any) => i.city === city)
|
||||||
|
const hSubCity = hSub.filter((i: any) => i.city === city)
|
||||||
|
const hNormalCity = hNormal.filter((i: any) => i.city === city)
|
||||||
|
const sTotal = [...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.total || 0), 0)
|
||||||
|
const hTotal = [...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.total || 0), 0)
|
||||||
return (
|
return (
|
||||||
<div key={city} className="border rounded-lg p-3">
|
<div key={city} className="border rounded-lg overflow-hidden">
|
||||||
<h3 className="text-sm font-medium mb-3 flex items-center gap-2">
|
<div className="bg-gray-50 px-4 py-2.5 flex items-center justify-between">
|
||||||
<span className="px-2 py-0.5 rounded bg-indigo-50 text-indigo-600 text-xs">{city}</span>
|
<div className="flex items-center gap-2">
|
||||||
|
<span className="px-2 py-0.5 rounded bg-indigo-50 text-indigo-600 text-xs font-medium">{city}</span>
|
||||||
<span className="text-gray-400 text-xs">向{city}社保/公积金经办机构申报</span>
|
<span className="text-gray-400 text-xs">向{city}社保/公积金经办机构申报</span>
|
||||||
</h3>
|
</div>
|
||||||
{sTable && <div className="mb-3"><h4 className="text-xs font-medium text-gray-600 mb-1">社保</h4>{sTable}</div>}
|
</div>
|
||||||
{hTable && <div><h4 className="text-xs font-medium text-gray-600 mb-1">公积金</h4>{hTable}</div>}
|
<div className="p-3 space-y-3">
|
||||||
|
<CollapsibleSection
|
||||||
|
title="社保"
|
||||||
|
icon={<Shield className="w-4 h-4 text-blue-500" />}
|
||||||
|
summary={`${sAddCity.length + sSubCity.length + sNormalCity.length} 人 | 企业 ¥${fmt([...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.totalOrg || 0), 0))} + 个人 ¥${fmt([...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.totalEmp || 0), 0))} = ¥${fmt(sTotal)}`}
|
||||||
|
defaultOpen={true}
|
||||||
|
>
|
||||||
|
{sTable}
|
||||||
|
</CollapsibleSection>
|
||||||
|
<CollapsibleSection
|
||||||
|
title="公积金"
|
||||||
|
icon={<Home className="w-4 h-4 text-green-500" />}
|
||||||
|
summary={`${hAddCity.length + hSubCity.length + hNormalCity.length} 人 | 企业 ¥${fmt([...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.orgAmount || 0), 0))} + 个人 ¥${fmt([...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.empAmount || 0), 0))} = ¥${fmt(hTotal)}`}
|
||||||
|
defaultOpen={true}
|
||||||
|
>
|
||||||
|
{hTable}
|
||||||
|
</CollapsibleSection>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@@ -492,3 +518,22 @@ export default function SocialInsurance() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function CollapsibleSection({ title, icon, summary, defaultOpen = false, children }: { title: string; icon: React.ReactNode; summary?: string; defaultOpen?: boolean; children: React.ReactNode }) {
|
||||||
|
const [open, setOpen] = useState(defaultOpen)
|
||||||
|
return (
|
||||||
|
<div className="border rounded-lg overflow-hidden">
|
||||||
|
<button
|
||||||
|
onClick={() => setOpen(!open)}
|
||||||
|
className="w-full flex items-center justify-between px-3 py-2 hover:bg-gray-50 transition-colors"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{open ? <ChevronDown className="w-4 h-4 text-gray-400" /> : <ChevronRight className="w-4 h-4 text-gray-400" />}
|
||||||
|
{icon}
|
||||||
|
<span className="text-sm font-medium">{title}</span>
|
||||||
|
{summary && <span className="text-xs text-gray-400 ml-2">{summary}</span>}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{open && <div className="px-3 pb-3 pt-1">{children}</div>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user