Towncouncil filter on Leaderboard

This commit is contained in:
ZacTohZY
2024-08-02 02:37:20 +08:00
parent 6b340c30c4
commit 42cae27ec6
3 changed files with 61 additions and 48 deletions

View File

@@ -19,7 +19,7 @@ const InsertImage: React.FC<InsertImageProps> = ({ onImageSelected }) => {
return (
<div
className="flex flex-col items-center p-5 bg-white dark:bg-zinc-800 rounded-md"
style={{ width: 350, height: 500 }}
style={{ width: 400, height: 500 }}
>
<input
type="file"
@@ -30,7 +30,7 @@ const InsertImage: React.FC<InsertImageProps> = ({ onImageSelected }) => {
<img
src={previewImage}
alt="Selected Image"
className="w-full h-full object-cover rounded-md"
className="w-full h-[410px] object-cover rounded-md"
/>
)}
</div>

View File

@@ -9,6 +9,7 @@ interface User {
id: string;
firstName: string;
lastName: string;
townCouncil: string;
}
interface CombinedData {
@@ -16,6 +17,7 @@ interface CombinedData {
formId: string;
name: string;
avgBill: number;
townCouncil: string;
}
export default function HBContestPage() {
@@ -33,15 +35,11 @@ export default function HBContestPage() {
};
const [combinedData, setCombinedData] = useState<CombinedData[]>([]);
const [filteredData, setFilteredData] = useState<CombinedData[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false);
const handleOpenModal = () => {
setIsModalOpen(true);
};
const [isInfoModalOpen, setIsInfoModalOpen] = useState(false);
const handleOpenInfoModal = () => setIsInfoModalOpen(true);
const [townCouncils, setTownCouncils] = useState<string[]>([]);
const [selectedTownCouncil, setSelectedTownCouncil] = useState<string>("");
useEffect(() => {
const fetchData = async () => {
@@ -61,6 +59,7 @@ export default function HBContestPage() {
formId: form.userId,
name: user ? `${user.firstName} ${user.lastName}` : "Unknown Name",
avgBill: form.avgBill,
townCouncil: user ? user.townCouncil : "Unknown Town Council",
};
});
@@ -68,6 +67,11 @@ export default function HBContestPage() {
combined.sort((a, b) => a.avgBill - b.avgBill);
setCombinedData(combined);
setFilteredData(combined);
// Fetch town councils
const townCouncilsResponse = await instance.get(`${config.serverAddress}/users/town-councils-metadata`);
setTownCouncils(JSON.parse(townCouncilsResponse.data).townCouncils);
} catch (error) {
console.log("Failed to fetch data");
}
@@ -76,8 +80,16 @@ export default function HBContestPage() {
fetchData();
}, []);
const topUser = combinedData.length > 0 ? combinedData[0] : null;
const top5Users = combinedData.slice(1, 10);
useEffect(() => {
// Filter combined data based on selected town council
const filtered = combinedData.filter((data) =>
selectedTownCouncil ? data.townCouncil === selectedTownCouncil : true
);
setFilteredData(filtered);
}, [selectedTownCouncil, combinedData]);
const topUser = filteredData.length > 0 ? filteredData[0] : null;
const top5Users = filteredData.slice(1, 10);
return (
<div className="flex flex-col items-center justify-center">
@@ -85,12 +97,12 @@ export default function HBContestPage() {
<section className="bg-red-50 dark:bg-primary-950 border border-primary-100 p-10 rounded-xl w-full max-w-2xl flex flex-col items-center">
<div className="w-full flex justify-end">
<Tooltip content="Information">
<Button isIconOnly variant="light" onPress={handleOpenInfoModal}>
<Button isIconOnly variant="light" onPress={() => setIsInfoModalOpen(true)}>
<InfoIcon />
</Button>
</Tooltip>
<Tooltip content="Leaderboard">
<Button isIconOnly variant="light" onPress={handleOpenModal}>
<Button isIconOnly variant="light" onPress={() => setIsModalOpen(true)}>
<TrophyIcon />
</Button>
</Tooltip>
@@ -142,19 +154,35 @@ export default function HBContestPage() {
<ModalHeader className="flex justify-center items-center font-bold text-2xl text-red-900">
<span>Leaderboard</span>
</ModalHeader>
<ModalBody className="pb-8"> {/* Add padding-bottom for white space */}
<div className="flex flex-col gap-4">
<ModalBody className="pb-8">
<div className="mb-4">
{townCouncils.length > 0 && (
<select
value={selectedTownCouncil}
onChange={(e) => setSelectedTownCouncil(e.target.value)}
>
<option value="">All locations</option>
{townCouncils.map((townCouncil) => (
<option key={townCouncil} value={townCouncil}>
{townCouncil}
</option>
))}
</select>
)}
</div>
<div className="flex flex-col gap-2">
{topUser && (
<div className="p-4 border rounded-md bg-red-100 flex items-center">
<div className="p-2 border rounded-md bg-red-100 dark:bg-primary-950 flex items-center">
<TrophyIcon />
<p className="text-lg flex-1 text-center font-bold">{topUser.name}</p> {/* Center text */}
<p className="text-lg flex-1 text-center font-bold">{topUser.name}</p>
</div>
)}
</div>
<div className="grid grid-rows-1 md:grid-rows-2 gap-4">
<div className="grid grid-rows-1 md:grid-rows-2 gap-2">
{top5Users.map((user, index) => (
<div key={user.userId} className="p-4 border rounded-md bg-red-100 flex items-center">
<span className="text-xl font-bold w-8">{index + 2}</span>
<div key={user.userId} className="p-3 border rounded-md bg-red-100 dark:bg-primary-950 flex items-center">
<span className="text-lg font-bold w-8">{index + 2}</span>
<span className="flex-1 text-center">{user.name}</span>
</div>
))}
@@ -178,35 +206,20 @@ export default function HBContestPage() {
<div className="space-y-4 text-gray-700 dark:text-gray-300">
<p className="font-semibold">Form Completion:</p>
<ul className="list-disc list-inside pl-4">
Participants must complete the online form, providing the following details
<li>Water bill amount</li>
<li>Electricity bill amount</li>
<li>Number of dependents</li>
Participants must fill out all required fields to complete the form.
</ul>
<p className="font-semibold">Document Upload</p>
<p className="font-semibold">Eligibility:</p>
<ul className="list-disc list-inside pl-4">
<li>Participants must upload clear, legible images of their water and electricity bills.</li>
<li>Both documents should clearly show the bill amount and date.</li>
Residents must be registered with the town council to be eligible.
</ul>
<p className="font-semibold">Data Accuracy</p>
<p className="font-semibold">Submission Deadline:</p>
<ul className="list-disc list-inside pl-4">
<li>All provided information must be accurate and truthful. Inaccurate or misleading information will result in disqualification.</li>
<li>All submitted bills and details will be subject to verification.</li>
</ul>
<p className="font-semibold">Privacy and Data Handling</p>
<ul className="list-disc list-inside pl-4">
<li>All personal data and bill images submitted will be handled in accordance with privacy regulations and will not be shared with third parties without consent.</li>
<li>Data will be used solely for contest purposes and to verify the validity of entries.</li>
Ensure to submit the form before the end of the month.
</ul>
</div>
</ModalBody>
</ModalContent>
</Modal>
</div >
</div>
);
}

View File

@@ -139,12 +139,12 @@ export default function HBFormPage() {
return (
<div className="w-full h-full">
<section className="w-7/12 mx-auto">
<Button variant="light" onPress={() => navigate(-1)}>
<ArrowUTurnLeftIcon />
</Button>
</section>
<section className="w-7/12 mx-auto p-5 bg-red-100 dark:bg-red-950 border border-primary-100 rounded-2xl h-600px">
<section className="w-8/12 mx-auto p-6 bg-red-100 dark:bg-red-950 border border-primary-100 rounded-2xl h-600px">
<div className="py-2">
<Button variant="light" onPress={() => navigate(-1)}>
<ArrowUTurnLeftIcon />
</Button>
</div>
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
@@ -170,7 +170,7 @@ export default function HBFormPage() {
<Form>
<div className="flex flex-col gap-5">
<div className="flex flex-row gap-10">
<div className="flex flex-col gap-10">
<div className="flex flex-col gap-5 p-1">
<NextUIFormikInput
label="Electrical Bill"
name="electricalBill"