diff --git a/view/next-project/src/components/budget_managements/BudgetManagement.tsx b/view/next-project/src/components/budget_managements/BudgetManagement.tsx index bcfe15cc0..2a904927d 100644 --- a/view/next-project/src/components/budget_managements/BudgetManagement.tsx +++ b/view/next-project/src/components/budget_managements/BudgetManagement.tsx @@ -1,69 +1,93 @@ -import { useState } from 'react'; +import { useRouter } from 'next/router'; +import { useState, useEffect } from 'react'; +import { + Department, + Division, + Item, + fetchDepartments, + fetchDivisions, + fetchItems, +} from './mockApi'; import { Card, EditButton, AddButton, Title } from '@/components/common'; import PrimaryButton from '@/components/common/OutlinePrimaryButton/OutlinePrimaryButton'; -interface RegistrationItem { - id: string; - name: string; - budget?: number; - used?: number; - remaining?: number; -} +export default function BudgetManagement() { + const router = useRouter(); + const { departmentId, divisionId } = router.query; -interface Department { - id: string; - name: string; - budget: number; - used: number; - remaining: number; -} + const [departments, setDepartments] = useState([]); + const [divisions, setDivisions] = useState([]); + const [items, setItems] = useState([]); -interface Division { - id: string; - name: string; - departmentId: string; - budget: number; - used: number; - remaining: number; -} + const [selectedDepartmentId, setSelectedDepartmentId] = useState(departmentId || ''); + const [selectedDivisionId, setSelectedDivisionId] = useState(divisionId || ''); -interface Item { - id: string; - name: string; - divisionId: string; - budget: number; - used: number; - remaining: number; -} + useEffect(() => { + fetchDepartments().then(setDepartments); + }, []); -interface BudgetManagementProps { - departments: Department[]; - divisions: Division[]; - items: Item[]; -} + useEffect(() => { + setSelectedDepartmentId(departmentId || ''); + }, [departmentId]); -export default function BudgetManagement({ departments, divisions, items }: BudgetManagementProps) { - const [selectedDepartmentId, setSelectedDepartmentId] = useState(''); - const [selectedDivisionId, setSelectedDivisionId] = useState(''); + useEffect(() => { + setSelectedDivisionId(divisionId || ''); + }, [divisionId]); - const handleDepartmentChange = (e: React.ChangeEvent) => { - setSelectedDepartmentId(e.target.value); - setSelectedDivisionId(''); - }; + useEffect(() => { + if (selectedDepartmentId) { + fetchDivisions(Number(selectedDepartmentId)).then(setDivisions); + setItems([]); + } else { + setDivisions([]); + setSelectedDivisionId(''); + setItems([]); + } - const handleDivisionChange = (e: React.ChangeEvent) => { - setSelectedDivisionId(e.target.value); - }; + router.push( + { + pathname: router.pathname, + query: { + ...router.query, + departmentId: selectedDepartmentId || undefined, + divisionId: undefined, + }, + }, + undefined, + { shallow: true }, + ); + }, [selectedDepartmentId]); + + useEffect(() => { + if (selectedDivisionId) { + fetchItems(Number(selectedDivisionId)).then(setItems); + } else { + setItems([]); + } + + router.push( + { + pathname: router.pathname, + query: { + ...router.query, + departmentId: selectedDepartmentId || undefined, + divisionId: selectedDivisionId || undefined, + }, + }, + undefined, + { shallow: true }, + ); + }, [selectedDivisionId]); - let displayItems: RegistrationItem[] = []; + let displayItems: any[] = []; let title = '購入報告'; const showBudgetColumns = true; if (selectedDivisionId) { - displayItems = items.filter((item) => item.divisionId === selectedDivisionId); + displayItems = items; title = '申請物品'; } else if (selectedDepartmentId) { - displayItems = divisions.filter((div) => div.departmentId === selectedDepartmentId); + displayItems = divisions; title = '申請部門'; } else { displayItems = departments; @@ -74,6 +98,26 @@ export default function BudgetManagement({ departments, divisions, items }: Budg const totalUsed = displayItems.reduce((sum, item) => sum + (item.used || 0), 0); const totalRemaining = displayItems.reduce((sum, item) => sum + (item.remaining || 0), 0); + const handleDepartmentChange = (e: React.ChangeEvent) => { + const deptId = e.target.value; + setSelectedDepartmentId(deptId); + setSelectedDivisionId(''); + }; + + const handleDivisionChange = (e: React.ChangeEvent) => { + const divId = e.target.value; + setSelectedDivisionId(divId); + }; + + const handleRowClick = (item: any) => { + if (!selectedDepartmentId) { + setSelectedDepartmentId(item.id); + setSelectedDivisionId(''); + } else if (!selectedDivisionId) { + setSelectedDivisionId(item.id); + } + }; + return (
@@ -105,13 +149,11 @@ export default function BudgetManagement({ departments, divisions, items }: Budg className='border-b border-black-300 focus:outline-none' > - {divisions - .filter((div) => div.departmentId === selectedDepartmentId) - .map((div) => ( - - ))} + {divisions.map((div) => ( + + ))}
@@ -136,56 +178,33 @@ export default function BudgetManagement({ departments, divisions, items }: Budg {displayItems.map((item, index) => ( - - -
-
- {item.name} - console.log('Edit clicked:', item.id)} /> -
-
- + handleRowClick(item)} + > +
+ {item.name} + +
+ {showBudgetColumns && ( <> - -
- {item.budget?.toLocaleString() || '-'} -
- - -
- {item.used?.toLocaleString() || '-'} -
- - -
- {item.remaining?.toLocaleString() || '-'} -
- + {item.budget} + {item.used} + {item.remaining} )} ))} {showBudgetColumns && displayItems.length > 0 && ( - -
合計
- - -
- {totalBudget.toLocaleString()} -
- - -
- {totalUsed.toLocaleString()} -
- - -
- {totalRemaining.toLocaleString()} -
- + 合計 + {totalBudget} + {totalUsed} + {totalRemaining} )} {displayItems.length === 0 && ( diff --git a/view/next-project/src/components/budget_managements/mockApi.ts b/view/next-project/src/components/budget_managements/mockApi.ts new file mode 100644 index 000000000..99dcce63f --- /dev/null +++ b/view/next-project/src/components/budget_managements/mockApi.ts @@ -0,0 +1,100 @@ +export interface Department { + id: number; + name: string; + budget: number; + used: number; + remaining: number; +} + +export interface Division { + id: number; + name: string; + departmentId: number; + budget: number; + used: number; + remaining: number; +} + +export interface Item { + id: number; + name: string; + divisionId: number; + budget: number; + used: number; + remaining: number; +} + +const departments: Department[] = [ + { id: 1, name: '制作局', budget: 20000, used: 5000, remaining: 15000 }, + { id: 2, name: '渉外局', budget: 18000, used: 4000, remaining: 14000 }, + { id: 3, name: '企画局', budget: 22000, used: 6000, remaining: 16000 }, + { id: 4, name: '財務局', budget: 25000, used: 5500, remaining: 19500 }, + { id: 5, name: '情報局', budget: 21000, used: 7000, remaining: 14000 }, + { id: 6, name: '総務局', budget: 23000, used: 4500, remaining: 18500 }, +]; + +const divisions: Division[] = [ + { id: 1, name: '制作部門A', departmentId: 1, budget: 10000, used: 3000, remaining: 7000 }, + { id: 2, name: '制作部門B', departmentId: 1, budget: 10000, used: 2000, remaining: 8000 }, + { id: 3, name: '渉外部門A', departmentId: 2, budget: 9000, used: 4000, remaining: 5000 }, + { id: 4, name: '渉外部門B', departmentId: 2, budget: 9000, used: 0, remaining: 9000 }, + { id: 5, name: '企画部門A', departmentId: 3, budget: 11000, used: 5000, remaining: 6000 }, + { id: 6, name: '企画部門B', departmentId: 3, budget: 11000, used: 1000, remaining: 10000 }, + { id: 7, name: '財務部門A', departmentId: 4, budget: 12500, used: 3000, remaining: 9500 }, + { id: 8, name: '財務部門B', departmentId: 4, budget: 12500, used: 2500, remaining: 10000 }, + { id: 9, name: '情報部門A', departmentId: 5, budget: 10500, used: 4000, remaining: 6500 }, + { id: 10, name: '情報部門B', departmentId: 5, budget: 10500, used: 3000, remaining: 7500 }, + { id: 11, name: '総務部門A', departmentId: 6, budget: 11500, used: 2000, remaining: 9500 }, + { id: 12, name: '総務部門B', departmentId: 6, budget: 11500, used: 2500, remaining: 9000 }, +]; + +const items: Item[] = [ + { id: 1, name: '物品A', divisionId: 1, budget: 5000, used: 1000, remaining: 4000 }, + { id: 2, name: '物品B', divisionId: 1, budget: 5000, used: 500, remaining: 4500 }, + { id: 3, name: '物品C', divisionId: 2, budget: 5000, used: 2000, remaining: 3000 }, + { id: 4, name: '物品D', divisionId: 2, budget: 5000, used: 0, remaining: 5000 }, + { id: 5, name: '物品E', divisionId: 3, budget: 5000, used: 3000, remaining: 2000 }, + { id: 6, name: '物品F', divisionId: 3, budget: 5000, used: 500, remaining: 4500 }, + { id: 7, name: '物品G', divisionId: 4, budget: 5000, used: 2000, remaining: 3000 }, + { id: 8, name: '物品H', divisionId: 4, budget: 5000, used: 1500, remaining: 3500 }, + { id: 9, name: '物品I', divisionId: 5, budget: 5000, used: 4000, remaining: 1000 }, + { id: 10, name: '物品J', divisionId: 5, budget: 5000, used: 3000, remaining: 2000 }, + { id: 11, name: '物品K', divisionId: 6, budget: 5000, used: 1000, remaining: 4000 }, + { id: 12, name: '物品L', divisionId: 6, budget: 5000, used: 1500, remaining: 3500 }, + { id: 13, name: '物品M', divisionId: 7, budget: 5000, used: 3000, remaining: 2000 }, + { id: 14, name: '物品N', divisionId: 7, budget: 5000, used: 2000, remaining: 3000 }, + { id: 15, name: '物品O', divisionId: 8, budget: 5000, used: 1000, remaining: 4000 }, + { id: 16, name: '物品P', divisionId: 8, budget: 5000, used: 2500, remaining: 2500 }, + { id: 17, name: '物品Q', divisionId: 9, budget: 5000, used: 4000, remaining: 1000 }, + { id: 18, name: '物品R', divisionId: 9, budget: 5000, used: 3000, remaining: 2000 }, + { id: 19, name: '物品S', divisionId: 10, budget: 5000, used: 1000, remaining: 4000 }, + { id: 20, name: '物品T', divisionId: 10, budget: 5000, used: 2500, remaining: 2500 }, + { id: 21, name: '物品U', divisionId: 11, budget: 5000, used: 4000, remaining: 1000 }, + { id: 22, name: '物品V', divisionId: 11, budget: 5000, used: 3000, remaining: 2000 }, + { id: 23, name: '物品W', divisionId: 12, budget: 5000, used: 1000, remaining: 4000 }, + { id: 24, name: '物品X', divisionId: 12, budget: 5000, used: 2500, remaining: 2500 }, +]; + +export const fetchDepartments = async (): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(departments); + }); + }); +}; + +export const fetchDivisions = async (departmentId: number): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(divisions.filter((division) => division.departmentId === departmentId)); + }); + }); +}; + +export const fetchItems = async (divisionId: number): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(items.filter((item) => item.divisionId === divisionId)); + }); + }); +};