From 2c783bdb703e4ad69c9f3f846c2c9e6a527ccc80 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Tue, 25 Mar 2025 17:23:30 -0400 Subject: Implemented admin dashboard --- web/src/app/quotes/page.js | 247 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 web/src/app/quotes/page.js (limited to 'web/src/app/quotes') diff --git a/web/src/app/quotes/page.js b/web/src/app/quotes/page.js new file mode 100644 index 0000000..27ae439 --- /dev/null +++ b/web/src/app/quotes/page.js @@ -0,0 +1,247 @@ +'use client'; +import { useState, useEffect } from "react"; +import Card from "@/app/components/Card"; +import Navbar from "@/app/components/Navbar"; +import { fetchWithAuth } from "@/utils/api"; + +export default function Quotes() { + const [pendingQuotes, setPendingQuotes] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [message, setMessage] = useState(null); + const [formData, setFormData] = useState({ + author: '', + authorImage: '', + quote: '', + year: '', + submitterID: '' + }); + + useEffect(() => { + fetchPendingQuotes(); + }, []); + + const fetchPendingQuotes = async () => { + try { + setLoading(true); + const response = await fetchWithAuth('/api/quotes/pending'); + + if (!response.ok) { + throw new Error('Failed to fetch pending quotes'); + } + + const data = await response.json(); + setPendingQuotes(data); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + + const handleInputChange = (e) => { + const { name, value } = e.target; + setFormData({ + ...formData, + [name]: value + }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setMessage(null); + + try { + const response = await fetchWithAuth('/api/quotes/add', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }); + + if (!response.ok) { + throw new Error('Failed to submit quote'); + } + + setMessage({ + type: 'success', + text: 'Quote submitted successfully' + }); + + // Reset form + setFormData({ + author: '', + authorImage: '', + quote: '', + year: '', + submitterID: '' + }); + } catch (err) { + setMessage({ + type: 'error', + text: err.message + }); + } + }; + + const handleApproveQuote = async (id) => { + if (window.confirm('Are you sure you want to approve this quote?')) { + try { + const response = await fetchWithAuth('/api/quotes/approve', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ id }) + }); + + if (!response.ok) { + throw new Error('Failed to approve quote'); + } + + setMessage({ + type: 'success', + text: 'Quote approved successfully' + }); + + // Refresh quotes + fetchPendingQuotes(); + } catch (err) { + setMessage({ + type: 'error', + text: err.message + }); + } + } + }; + + const handleRejectQuote = async (id) => { + if (window.confirm('Are you sure you want to reject this quote?')) { + try { + const response = await fetchWithAuth('/api/quotes/reject', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ id }) + }); + + if (!response.ok) { + throw new Error('Failed to reject quote'); + } + + setMessage({ + type: 'success', + text: 'Quote rejected successfully' + }); + + // Refresh quotes + fetchPendingQuotes(); + } catch (err) { + setMessage({ + type: 'error', + text: err.message + }); + } + } + }; + + return ( + <> + +
+

Submit New Quote

+
+ + +