diff --git a/public/data.json b/public/data.json index 4bfc180..f2394c4 100644 --- a/public/data.json +++ b/public/data.json @@ -1 +1,8 @@ -{"stability":0.4,"development":0.66,"healthcare":0.2,"escape":0,"basicNeeds":0,"totalPeople":0} \ No newline at end of file +{ + "stability": 0.3, + "development": 0.5, + "healthcare": 0.2, + "escape": 0.1, + "basicNeeds": 0.1, + "totalPeople": 0.4 +} \ No newline at end of file diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 8fcc28c..bfeb03c 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -2,13 +2,36 @@ import React, { useState } from "react" -interface FormData { +type dataFields = + | "stability" + | "development" + | "healthcare" + | "escape" + | "basicNeeds" + | "totalPeople" + +const data_fields: dataFields[] = [ + "stability", + "development", + "healthcare", + "escape", + "basicNeeds", + "totalPeople", +] + +type FormData = { pinNumber: string -} +} & Record function AdminLogin() { const [formData, setFormData] = useState({ pinNumber: "", + stability: 0, + development: 0, + healthcare: 0, + escape: 0, + basicNeeds: 0, + totalPeople: 0, }) const handleInputChange = (event: React.ChangeEvent) => { @@ -22,14 +45,24 @@ function AdminLogin() { const handleFormSubmit = (e: { preventDefault: () => void }) => { e.preventDefault() - const verifyPIN = async (pin: string) => { + const updateProportions = async (fd: FormData) => { try { - const res = await fetch(`/api/verify/`, { + const res = await fetch(`/api/update/`, { method: "Post", headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ pin: pin }), + body: JSON.stringify({ + pin: fd.pinNumber, + data: { + stability: fd.stability, + development: fd.development, + healthcare: fd.healthcare, + escape: fd.escape, + basicNeeds: fd.basicNeeds, + totalPeople: fd.totalPeople, + }, + }), }) if (!res.ok) { throw new Error(res.statusText) @@ -42,7 +75,7 @@ function AdminLogin() { console.error("Error verifying PIN:", error) } } - verifyPIN(formData.pinNumber) + updateProportions(formData) } const [password, setPassword] = useState("") @@ -112,9 +145,33 @@ function AdminLogin() { +
+ +
+ {data_fields.map((field) => ( +
+ + +
+ ))} +
- diff --git a/src/app/api/data/route.ts b/src/app/api/data/route.ts index 8deab12..b383b4d 100644 --- a/src/app/api/data/route.ts +++ b/src/app/api/data/route.ts @@ -1,18 +1,8 @@ import { NextResponse } from "next/server" +import * as data from "../../../../public/data.json" export async function GET(request: Request) { - // the json format: - return NextResponse.json( - { - stability: 0.3, - development: 0.5, - healthcare: 0.2, - escape: 0.1, - basicNeeds: 0.1, - totalPeople: 0.4, - }, - { status: 200 }, - ) + return NextResponse.json(data, { status: 200 }) } // { "dollarsRaised": 500000, diff --git a/src/app/api/update/route.ts b/src/app/api/update/route.ts new file mode 100644 index 0000000..7728eb5 --- /dev/null +++ b/src/app/api/update/route.ts @@ -0,0 +1,143 @@ +import { Proportions } from "@/app/types" +import { NextResponse } from "next/server" + +export async function POST(req: Request) { + const j = await req.json() + console.log(j) + + // get the user pin + const userPin = j.pin + // get the password from the env file + const actualPin = process.env.PRIVATE_KEY + const token = process.env.GITHUB_TOKEN + + // check if the pin is null + if (userPin === null) { + return NextResponse.json({ response: "No Pin" }, { status: 400 }) + } + + console.log("pin success") + + if (token === null) { + return NextResponse.json({ response: "No Token" }, { status: 500 }) + } + + console.log("token success") + + // compare the + if (actualPin !== userPin) { + return NextResponse.json({ response: "Incorrect Pin" }, { status: 200 }) + } + + console.log("pin correct") + + // get the new data + const json: Proportions = j.data + + // check that all the data can be converted to numbers + if ( + isNaN(json.stability) || + isNaN(json.development) || + isNaN(json.healthcare) || + isNaN(json.escape) || + isNaN(json.basicNeeds) || + isNaN(json.totalPeople) + ) { + return NextResponse.json( + { response: "Invalid data, must be a number" }, + { status: 200 }, + ) + } else { + json.stability = Number(json.stability) + json.development = Number(json.development) + json.healthcare = Number(json.healthcare) + json.escape = Number(json.escape) + json.basicNeeds = Number(json.basicNeeds) + json.totalPeople = Number(json.totalPeople) + } + + console.log("data success") + + // check that the data is valid, all numbers between 0 and 1 + if ( + json.stability < 0 || + json.stability > 1 || + json.development < 0 || + json.development > 1 || + json.healthcare < 0 || + json.healthcare > 1 || + json.escape < 0 || + json.escape > 1 || + json.basicNeeds < 0 || + json.basicNeeds > 1 + ) { + return NextResponse.json( + { response: "Invalid data, must be between 0 and 1" }, + { status: 200 }, + ) + } + + console.log("data valid") + + const content = Buffer.from(JSON.stringify(json)).toString("base64") + + console.log("content success") + + // get the sha of the file + const responseSha = await fetch( + "https://api.github.com/repos/rice-apps/united-way/contents/public/data.json", + { + method: "GET", + headers: { + Accept: "application/vnd.github+json", + Authorization: `Bearer ${token}`, + "X-GitHub-Api-Version": "2022-11-28", + }, + }, + ) + + if (!responseSha.ok) { + console.log("error") + console.log(responseSha) + return NextResponse.error() + } + + const sha = (await responseSha.json()).sha + + console.log("sha success: " + sha) + + // send a commit to github + const response = await fetch( + "https://api.github.com/repos/rice-apps/united-way/contents/public/data.json", + { + method: "PUT", + headers: { + Accept: "application/vnd.github+json", + Authorization: `Bearer ${token}`, + "X-GitHub-Api-Version": "2022-11-28", + }, + body: JSON.stringify({ + message: "Update proportions", + committer: { + name: "United Way RiceApps", + email: "united-way-bot", + }, + sha: sha, + content: content, + }), + }, + ) + + if (!response.ok) { + console.log("error") + console.log(response) + return NextResponse.error() + } else { + console.log("response success") + console.log(response) + return NextResponse.json( + { response: "Updated proportions" }, + { status: 200 }, + ) + } +} diff --git a/src/app/donations/Donation.tsx b/src/app/donations/Donation.tsx index 0b48c33..cb00e2a 100644 --- a/src/app/donations/Donation.tsx +++ b/src/app/donations/Donation.tsx @@ -2,6 +2,7 @@ import ImpactCarousel from "./ImpactCarousel" import { useEffect, useState } from "react" import { Downloads } from "./Downloads" +import { Proportions } from "../types" type DonationInputs = { companyName: string | null @@ -19,7 +20,7 @@ function Donation({ companyName, dollarsRaised }: DonationInputs) { } // get the proportions - const [proportionsMap, setProportionsMap] = useState(null) + const [proportionsMap, setProportionsMap] = useState(null) useEffect(() => { GetData() diff --git a/src/app/types.ts b/src/app/types.ts new file mode 100644 index 0000000..87b1509 --- /dev/null +++ b/src/app/types.ts @@ -0,0 +1,8 @@ +export type Proportions = { + stability: number + development: number + healthcare: number + escape: number + basicNeeds: number + totalPeople: number +} diff --git a/tailwind.config.ts b/tailwind.config.ts index 300f05c..4a79453 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -24,7 +24,7 @@ const config: Config = { translate: { "30": "7.5rem", }, - // can add or overridee styles here + // can add or override styles here colors: { blue: "#015191", purple: "#804B67",