-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7 from crab85193/develop
マルチカテゴリ対応の人口推移グラフ機能追加および関連修正
- Loading branch information
Showing
17 changed files
with
740 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import React, { useState } from "react"; | ||
import { | ||
LineChart, | ||
Line, | ||
XAxis, | ||
YAxis, | ||
CartesianGrid, | ||
Tooltip, | ||
Legend, | ||
ResponsiveContainer, | ||
} from "recharts"; | ||
|
||
interface PopulationData { | ||
year: number; | ||
value: number; | ||
rate: number; | ||
} | ||
|
||
interface PrefectureCategoryData { | ||
prefName: string; | ||
data: PopulationData[]; | ||
} | ||
|
||
interface AllCategoriesData { | ||
[categoryName: string]: PrefectureCategoryData[]; | ||
} | ||
|
||
interface PopulationChartProps { | ||
allCategoriesData: AllCategoriesData; | ||
} | ||
|
||
const categories = ["総人口", "年少人口", "生産年齢人口", "老年人口"]; | ||
|
||
const colorMap: { [prefName: string]: string } = {}; | ||
|
||
const generateRandomColor = (): string => { | ||
const letters = "0123456789ABCDEF"; | ||
let color = "#"; | ||
for (let i = 0; i < 6; i++) { | ||
color += letters[Math.floor(Math.random() * 16)]; | ||
} | ||
return color; | ||
}; | ||
|
||
const getColorForPrefName = (pName: string) => { | ||
if (!colorMap[pName]) { | ||
colorMap[pName] = generateRandomColor(); | ||
} | ||
return colorMap[pName]; | ||
}; | ||
|
||
const PopulationChart: React.FC<PopulationChartProps> = ({ | ||
allCategoriesData, | ||
}) => { | ||
const [selectedCategory, setSelectedCategory] = useState<string>( | ||
categories[0] | ||
); | ||
|
||
const prefectureDataArray = allCategoriesData[selectedCategory] || []; | ||
|
||
if (prefectureDataArray.length === 0) { | ||
return <p>選択中のカテゴリのデータがありません</p>; | ||
} | ||
|
||
const allYears = prefectureDataArray.flatMap((p) => | ||
p.data.map((d) => d.year) | ||
); | ||
const uniqueYears = Array.from(new Set(allYears)).sort((a, b) => a - b); | ||
|
||
const combinedData = uniqueYears.map((year) => { | ||
const entry: { [key: string]: number | string } = { year }; | ||
for (const pData of prefectureDataArray) { | ||
const yearData = pData.data.find((d) => d.year === year); | ||
entry[pData.prefName] = yearData ? yearData.value : 0; | ||
} | ||
return entry; | ||
}); | ||
|
||
const prefNames = prefectureDataArray.map((p) => p.prefName); | ||
|
||
return ( | ||
<div style={{ width: "100%", height: "500px" }}> | ||
{/* カテゴリ切り替えUI */} | ||
<div style={{ marginBottom: "10px" }}> | ||
{categories.map((cat) => ( | ||
<button | ||
key={cat} | ||
onClick={() => setSelectedCategory(cat)} | ||
style={{ | ||
marginRight: "5px", | ||
padding: "5px 10px", | ||
backgroundColor: cat === selectedCategory ? "#007bff" : "#e0e0e0", | ||
color: cat === selectedCategory ? "#fff" : "#000", | ||
border: "none", | ||
borderRadius: "3px", | ||
cursor: "pointer", | ||
}} | ||
> | ||
{cat} | ||
</button> | ||
))} | ||
</div> | ||
|
||
<ResponsiveContainer width="100%" height="100%"> | ||
<LineChart | ||
data={combinedData} | ||
margin={{ top: 20, right: 30, left: 20, bottom: 5 }} | ||
> | ||
<CartesianGrid strokeDasharray="3 3" /> | ||
<XAxis dataKey="year" /> | ||
<YAxis /> | ||
<Tooltip /> | ||
<Legend /> | ||
{prefNames.map((pName) => ( | ||
<Line | ||
key={pName} | ||
type="monotone" | ||
dataKey={pName} | ||
name={pName} | ||
stroke={getColorForPrefName(pName)} | ||
/> | ||
))} | ||
</LineChart> | ||
</ResponsiveContainer> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PopulationChart; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { useState, useEffect } from "react"; | ||
import { fetchPopulation } from "../api/population"; | ||
import { PopulationCategory } from "../types/population"; | ||
|
||
const usePopulation = (prefCode: number | null) => { | ||
const [data, setData] = useState<PopulationCategory[]>([]); | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState<string | null>(null); | ||
|
||
useEffect(() => { | ||
if (!prefCode) return; | ||
|
||
const fetchData = async () => { | ||
setLoading(true); | ||
setError(null); | ||
try { | ||
const result = await fetchPopulation(prefCode.toString()); | ||
setData(result); | ||
} catch (err) { | ||
setError("人口データの取得に失敗しました. " + err); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
fetchData(); | ||
}, [prefCode]); | ||
|
||
return { data, loading, error }; | ||
}; | ||
|
||
export default usePopulation; |
Oops, something went wrong.