-
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.
SC-4 - Created account page. Added pie-chart.tsx which can be passed …
…a list of names and a list of numbers and create a pie chart with it.
- Loading branch information
1 parent
819f0aa
commit 99da1c7
Showing
2 changed files
with
165 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { JSX } from "react"; | ||
import React, { useState } from "react"; | ||
|
||
interface PieChartProps { | ||
data: number[]; | ||
colors?: string[]; | ||
labels?: string[]; | ||
} | ||
|
||
const defaultColors = [ | ||
"#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF", "#FF9F40" | ||
]; | ||
|
||
const PieChart: React.FC<PieChartProps> = ({ data, colors = defaultColors, labels = [] }) => { | ||
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null); | ||
|
||
const total = data.reduce((acc, value) => acc + value, 0); | ||
|
||
// Combine sections with values less than 10% into an "Other" section | ||
const combinedData = data.reduce<{ data: number[], labels: string[] }>((acc, value, index) => { | ||
if ((value / total) * 100 < 10) { | ||
if (acc.labels.includes("Other")) { | ||
acc.data[acc.labels.indexOf("Other")] += value; | ||
} else { | ||
acc.data.push(value); | ||
acc.labels.push("Other"); | ||
} | ||
} else { | ||
acc.data.push(value); | ||
acc.labels.push(labels[index] || ""); | ||
} | ||
return acc; | ||
}, { data: [], labels: [] }); | ||
|
||
let cumulativeValue = 0; | ||
|
||
return ( | ||
<svg width="400" height="400" viewBox="0 0 32 32"> | ||
{combinedData.data.map((value, index) => { | ||
const [startX, startY] = getCoordinatesForPercent(cumulativeValue / total); | ||
cumulativeValue += value; | ||
const [endX, endY] = getCoordinatesForPercent(cumulativeValue / total); | ||
const largeArcFlag = value / total > 0.5 ? 1 : 0; | ||
const [labelX, labelY] = getCoordinatesForPercent((cumulativeValue - value / 2) / total); | ||
|
||
// Adjust label position to avoid clipping | ||
const adjustedLabelX = (labelX + 16) / 2; | ||
const adjustedLabelY = (labelY + 16) / 2; | ||
|
||
const isHovered = index === hoveredIndex; | ||
const translateFactor = isHovered ? 0.25 : 0; // Increased translation factor | ||
const translateX = isHovered ? (labelX - 16) * translateFactor : 0; | ||
const translateY = isHovered ? (labelY - 16) * translateFactor : 0; | ||
const transform = `translate(${translateX}, ${translateY})`; | ||
|
||
return ( | ||
<g key={index} onMouseEnter={() => setHoveredIndex(index)} onMouseLeave={() => setHoveredIndex(null)}> | ||
<path | ||
d={`M16 16 L ${startX} ${startY} A 12 12 0 ${largeArcFlag} 1 ${endX} ${endY} Z`} // Reduced radius from 16 to 12 | ||
fill={colors[index % colors.length]} | ||
transform={transform} | ||
style={{ transition: 'transform 0.2s' }} | ||
/> | ||
{combinedData.labels[index] && ( | ||
<text x={adjustedLabelX} y={adjustedLabelY} fill="#000" fontSize="1.5" textAnchor="middle" dominantBaseline="middle" transform={transform} style={{ transition: 'transform 0.2s' }}> | ||
{combinedData.labels[index]} | ||
</text> | ||
)} | ||
<text x={adjustedLabelX} y={adjustedLabelY + 1.5} fill="#000" fontSize="1" textAnchor="middle" dominantBaseline="middle" transform={transform} style={{ transition: 'transform 0.2s' }}> | ||
{((value / total) * 100).toFixed(1)}% | ||
</text> | ||
{/* This is for testing and should be deleted later */} | ||
{/* <rect x="0" y="0" width="32" height="32" fill="none" stroke="black" strokeWidth="0.5" /> | ||
<circle cx="16" cy="16" r="0.5" fill="black" /> */} | ||
</g> | ||
); | ||
})} | ||
</svg> | ||
); | ||
}; | ||
|
||
const getCoordinatesForPercent = (percent: number) => { | ||
const radius = 12; // Reduced radius from 16 to 12 | ||
const x = Math.cos(2 * Math.PI * percent) * radius + 16; | ||
const y = Math.sin(2 * Math.PI * percent) * radius + 16; | ||
|
||
return [x, y]; | ||
}; | ||
|
||
export default PieChart; |
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,75 @@ | ||
import { JSX } from "react"; | ||
import PieChart from "@/components/pie-chart"; | ||
|
||
|
||
const Account = (): JSX.Element => { | ||
const user_name = "USER_NAME"; | ||
const stocks_owned = ["Stock 1", "Stock 2", "Stock 3", "Stock 4", "Stock 5", "Stock 6", "Stock 7"]; | ||
const stocks_owned_values = [300.50, 500.00, 199.50, 100.009, 50.119, 50.00, 150.34]; | ||
const number_of_stocks_owned_per_stock = [3, 1, 1, 4, 1, 1, 3]; | ||
let stock_total_value = 0 | ||
for (let i = 0; i < stocks_owned.length; i++){ | ||
stock_total_value += stocks_owned_values[i] * number_of_stocks_owned_per_stock[i]; | ||
} | ||
const charities_donated_to = ["Charity 1", "Charity 2", "Charity 3", "Charity 4", "Charity 5", "Charity 6", "Charity 7"]; | ||
const donations_made = [100.00, 50.00, 25.00, 10.00, 5.00, 5.00, 5.00]; | ||
|
||
return ( | ||
<> | ||
<div className="flex flex-row justify-around items-start p-4 text-black"> | ||
<div className="flex flex-col justify-around items-start p-4 text-black"> | ||
|
||
{/* Welcome message */} | ||
<div className="py-10 px-20 w-full max-w-lg grid grid-cols-1 gap-6"> | ||
<div className=""> | ||
<h2 className="text-4xl font-semibold tracking-tight text-gray-900 sm:text-5xl"> | ||
Hello {user_name}, | ||
</h2> | ||
<p className="mt-4 text-lg text-gray-600"> | ||
Thanks for supporting those in need through Stock Charity! | ||
</p> | ||
</div> | ||
</div> | ||
<div className="flex flex-col justify-around items-start p-4 text-black"> | ||
{/* Stocks information */} | ||
<div className="flex flex-row gap-10 justify-around items-start"> | ||
|
||
{/* Stocks owned */} | ||
<div className="bg-gray-300 p-2 rounded-md"> | ||
<h3 className="text-lg font-bold">Stocks owned:</h3> | ||
<p>Total stock value: ${stock_total_value.toFixed(2)}</p> | ||
<br></br> | ||
|
||
|
||
{stocks_owned.map((stock, index) => ( | ||
<ul key={index}>{number_of_stocks_owned_per_stock[index]} stocks of {stock} worth ${stocks_owned_values[index].toFixed(2)} each</ul> | ||
))} | ||
|
||
</div> | ||
|
||
{/* Dividends earned */} | ||
<div className="bg-gray-300 p-2 rounded-md"> | ||
<h3 className="text-lg font-bold">Dividends earned:</h3> | ||
<p>Total dividends earned: $27.62</p> | ||
<br></br> | ||
<p>$5.43 on Jan. 16th 2025 from {stocks_owned[2]}</p> | ||
<p>$6.76 on Oct. 23th 2024 from {stocks_owned[1]}</p> | ||
<p>$15.43 on Aug. 6th 2024 from {stocks_owned[0]}</p> | ||
|
||
|
||
</div> | ||
|
||
</div> | ||
</div> | ||
</div> | ||
{/* Pie chart of stocks owned */} | ||
<div className="flex flex-col items-center justify-center py-9 text-black"> | ||
<p className="text-lg font-bold">Your impact:</p> | ||
<PieChart data={donations_made} labels={charities_donated_to} /> | ||
</div> | ||
</div> | ||
</> | ||
); | ||
} | ||
|
||
export default Account; |