diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 842a15f..fd1aac0 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,9 +5,24 @@ + - + + + + + + + + + + + + + + + @@ -106,6 +121,14 @@ + + + + + + + + diff --git a/frontend/src/app/auth/admin/forgot-password/page.tsx b/frontend/src/app/auth/admin/forgot-password/page.tsx new file mode 100644 index 0000000..8a49a0f --- /dev/null +++ b/frontend/src/app/auth/admin/forgot-password/page.tsx @@ -0,0 +1,127 @@ +'use client'; +import { FC, FormEventHandler, useEffect, useState } from 'react'; +import Image from 'next/image'; +import { TextInput } from '@/components/core/TextInput'; +import { Button } from '@/components/core/Button'; +import Link from 'next/link'; +import { useRouter, useSearchParams } from 'next/navigation'; +import { useUserContext } from '@/context/userContext'; +import { CodeInput } from '@/components/auth/CodeInput'; +import { cookies } from 'next/headers'; + +interface PageProps {} + +const Page: FC = () => { + const [emailInput, setEmailInput] = useState(''); + const [passwordInput, setPasswordInput] = useState(''); + const [confirmPasswordInput, setConfirmPasswordInput] = useState(''); + const router = useRouter(); + const searchParams = useSearchParams(); + + const jwt = searchParams.get('jwt'); + + const handleSubmit: FormEventHandler = (e) => { + e.preventDefault(); + + if (!jwt) { + fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/auth/admin/forgot-password`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + email: emailInput, + }), + credentials: 'include', + } + ).catch((err) => console.error(err)); + } else { + fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/auth/admin/verify-forgot-password`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + token: jwt, + password: passwordInput, + }), + credentials: 'include', + } + ) + .then((res) => { + if (res.ok) { + router.push('/auth/login'); + } + }) + .catch((err) => console.error(err)); + } + }; + + if (jwt) { + return ( +
+
+ logo + + Forgot Password + + + +
+ ); + } + + return ( +
+
+ logo + + Forgot Password + + +
+ ); +}; + +export default Page; diff --git a/frontend/src/app/auth/login/page.tsx b/frontend/src/app/auth/login/page.tsx index 61c6283..b892d3a 100644 --- a/frontend/src/app/auth/login/page.tsx +++ b/frontend/src/app/auth/login/page.tsx @@ -142,18 +142,11 @@ const Page: FC = () => { {loginType === 'ADMIN' && ( - Forgot Username or Password? + Forgot Password? )} - - - @@ -182,28 +185,32 @@ export default function InformationForm() { className={`text-left ${ formPage == 'Information' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Information')} + }`} + onClick={() => setFormPage('Information')} > Pet Information diff --git a/frontend/src/app/form/Assessment.tsx b/frontend/src/app/delivery-form/Assessment.tsx similarity index 100% rename from frontend/src/app/form/Assessment.tsx rename to frontend/src/app/delivery-form/Assessment.tsx diff --git a/frontend/src/app/form/Confirmation.tsx b/frontend/src/app/delivery-form/Confirmation.tsx similarity index 100% rename from frontend/src/app/form/Confirmation.tsx rename to frontend/src/app/delivery-form/Confirmation.tsx diff --git a/frontend/src/app/form/Pet.tsx b/frontend/src/app/delivery-form/Pet.tsx similarity index 100% rename from frontend/src/app/form/Pet.tsx rename to frontend/src/app/delivery-form/Pet.tsx diff --git a/frontend/src/app/form/Submit.tsx b/frontend/src/app/delivery-form/Submit.tsx similarity index 100% rename from frontend/src/app/form/Submit.tsx rename to frontend/src/app/delivery-form/Submit.tsx diff --git a/frontend/src/app/form/client.tsx b/frontend/src/app/delivery-form/client.tsx similarity index 100% rename from frontend/src/app/form/client.tsx rename to frontend/src/app/delivery-form/client.tsx diff --git a/frontend/src/app/form/page.tsx b/frontend/src/app/delivery-form/page.tsx similarity index 92% rename from frontend/src/app/form/page.tsx rename to frontend/src/app/delivery-form/page.tsx index 5a68ec1..b46d0a6 100644 --- a/frontend/src/app/form/page.tsx +++ b/frontend/src/app/delivery-form/page.tsx @@ -8,7 +8,6 @@ import { Button } from '../../components/core/Button'; import Assessment from './Assessment'; import Submit from './Submit'; import Confirmation from './Confirmation'; -import { API_BASE_URL } from '../globals'; export default function DeliveryReportForm() { const [formPage, setFormPage] = useState('Client'); @@ -126,13 +125,16 @@ export default function DeliveryReportForm() { } try { - const response = await fetch(`${API_BASE_URL}/deliveries`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(deliveryReportData), - }); + const response = await fetch( + `${process.env.NEXT_PUBLIC_API_BASE_URL}/deliveries`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(deliveryReportData), + } + ); if (response.ok) { const data = await response.json(); @@ -183,7 +185,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Client' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Client')} + }`} + onClick={() => setFormPage('Client')} > Client @@ -191,7 +194,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Pet1' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Pet1')} + }`} + onClick={() => setFormPage('Pet1')} > Pet 1 @@ -199,7 +203,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Pet2' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Pet2')} + }`} + onClick={() => setFormPage('Pet2')} > Pet 2 @@ -207,7 +212,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Pet3' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Pet3')} + }`} + onClick={() => setFormPage('Pet3')} > Pet 3 @@ -215,7 +221,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Assessment' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Assessment')} + }`} + onClick={() => setFormPage('Assessment')} > Needs Assessment @@ -223,7 +230,8 @@ export default function DeliveryReportForm() { className={`text-left ${ formPage == 'Submit' && 'font-bold text-secondary' - }`}onClick={() => setFormPage('Submit')} + }`} + onClick={() => setFormPage('Submit')} > Submit diff --git a/frontend/src/app/globals.ts b/frontend/src/app/globals.ts deleted file mode 100644 index 6acb415..0000000 --- a/frontend/src/app/globals.ts +++ /dev/null @@ -1 +0,0 @@ -export const API_BASE_URL = 'https://combined-community-action.vercel.app'; diff --git a/frontend/src/app/reports/Chart.tsx b/frontend/src/app/reports/Chart.tsx index 205e772..c3d3e8e 100644 --- a/frontend/src/app/reports/Chart.tsx +++ b/frontend/src/app/reports/Chart.tsx @@ -2,19 +2,11 @@ import { useEffect, useState, useRef, MouseEvent } from 'react'; import ChartJS from 'chart.js/auto'; import { calcAllLbsPerBrand, calculateLbsPerBrand } from './Dashboard'; -import fetchClientById from './Dashboard'; -import fetchOrderByLocation from './Dashboard'; -import fetchOrderByBrand from './Dashboard'; -import fetchOrderByDate from './Dashboard'; import { Button } from '@/components/core/Button'; import jsPDF from 'jspdf'; import 'jspdf-autotable'; import html2canvas from 'html2canvas'; -import getSelectedLocation from './Dashboard'; - -//import 'chartjs-adapter-date-fns'; // Import adapter for date formatting (optional) - interface PieChartData { labels: string[]; data: number[]; diff --git a/frontend/src/app/reports/Dashboard.tsx b/frontend/src/app/reports/Dashboard.tsx index 7407876..8e65909 100644 --- a/frontend/src/app/reports/Dashboard.tsx +++ b/frontend/src/app/reports/Dashboard.tsx @@ -2,31 +2,6 @@ import { MouseEvent, useEffect, useState } from 'react'; import Chart from './Chart'; import { Button } from '@/components/core/Button'; -//import Client from '../../../../backend/schemas/client_schema'; -import { Server } from 'http'; -//import { Request, Response, NextFunction } from 'express'; -//import Volunteer from '../volunteer/page' -//import { ______ } from "../backend/routes/order_route.ts"; -//import orderModel from '../../../../backend/schemas/order_schema'; - -//const response = await request(server).get(`/admin/${adminId}`); - -/** - TO DO: - - only have ACTIVE pets - - filters - - order's client's location - - look at each order's client and filter by their location - - order's brands - - look at the chosen brand and display the weight only for that - - look at each order's brands and sort the weight and brand for each - - order's dates - - take the chosen date and compare its month and year to the - data's month and year - - look at each order's dates and - */ - -//co nsole.log("month:" + new Date("2016-09-23T12:00:00Z").getMonth()); export function getWeightsByLocation( orderData: any[], diff --git a/frontend/src/components/core/Navbar.tsx b/frontend/src/components/core/Navbar.tsx index 0660a9f..52e3bed 100644 --- a/frontend/src/components/core/Navbar.tsx +++ b/frontend/src/components/core/Navbar.tsx @@ -38,9 +38,11 @@ export const Navbar: FC = () => { {accountType === 'ADMIN' && ( <> Form @@ -48,7 +50,9 @@ export const Navbar: FC = () => { Client Dashboard @@ -56,13 +60,21 @@ export const Navbar: FC = () => { Reports )} + {accountType === 'VOLUNTEER' && ( + + )}
{accountType ? ( diff --git a/frontend/tmp.md b/frontend/tmp.md new file mode 100644 index 0000000..5404de5 --- /dev/null +++ b/frontend/tmp.md @@ -0,0 +1,98 @@ +## Deployment Process + +### Production + +#### Backend Deployment + +1. **Commit and Pull Request to Main:** + - Make your changes and commit them. + - Create a pull request to merge your changes into the main branch. + +2. **Merge to Staging:** + - After your changes have been merged to main and were thoroughly tested in the development environment, create a + pull request to merge them into the staging branch. + +3. **Merge to Release Branch:** + - Once your changes are merged into the staging branch and tested in the staging environment, create a pull request + to merge them into the release branch. + +4. **Create Release:** + - Upon merging into the release branch, create a new release. + - Use semantic versioning (e.g., `v0.0.1`) for the release tag. + +5. **Add Release Notes:** + - Write release notes manually or auto-generate them from commits. + - Ensure clarity and completeness in the release notes. + +6. **Release Workflow:** + - The release workflow defined in `.github/google-release.yaml` will be triggered automatically once the release is + created. + - This workflow deploys updated Kubernetes resources to the production cluster. + +7. **Confirmation:** + - Confirm that the production server is up and running after deployment. + +## Environment Configuration + +### Backend + +Ensure correct setup of critical environment variables in the target environment: + +- **MONGODB_URI**: + - Points to the MongoDB cluster, shared between development and production. +- **MONGODB_DB_NAME**: + - Specifies the name of the database (`dev` for development, `prod` for production). +- **DEBUG**: + - Set to `true` only in development to initialize the logger with development presets. +- **MEDIA_BUCKET**: + - URL for Google Cloud Storage media bucket. +- **MATCHES_GENERATION_TOPIC_NAME**: + - Pub/Sub topic name for matches generation (`matches-generation` for development, `matches-generation-prod` for + production). +- **MATCHES_GENERATION_SUBSCRIPTION_ID**: + - Subscription ID for the Pub/Sub topic. +- **FIREBASE_ENABLED**: + - Set to `true` in production; can be `false` during development if Firebase is not configured. + +**Auth0 Configuration** (Tenant-specific): + +- **JWT_ISSUER** +- **JWT_AUDIENCE** +- **AUTH0_TENANT_NAME** +- **M2M_CLIENT_ID** +- **M2M_CLIENT_SECRET** + +Ensure these variables are configured according to the appropriate Auth0 tenant (`dev-4zf60z3hqoxfjz7m` for +development/test, `prod-f2m` for production). + +# Services + +## MongoDB + +| Description | Dev | Test | Prod | staging | +|--------------|-------------------|-------------------|-------------------|-------------------| +| Organization | Development's Org | Development's Org | Development's Org | Development's Org | +| Project | F2M-dev | F2M-dev | F2M-prod | F2M-staging | +| Cluster | F2M-dev | F2M-dev | F2M-prod | F2M-staging | + +## GCP/Firebase + +| Description | Dev | Test | Prod | Staging | +|----------------------------|---------------------------------|---------------------------------|-----------------------|----------------------------| +| Project | Friend2Meet-dev | Friend2Meet-dev | Friend2Meet-dev | Friend2Meet-dev | +| GKE Cluster | autopilot-dev-us-central1 | gke-test-cluster | autopilot-cluster-1 | ftm-staging | +| Storage Bucket | dev.media.friend2meet.com | dev.media.friend2meet.com | media.friend2meet.com | staging.friend2meet.com | +| Cloud Tasks Queue | matches-generation-dev | N/A | matches-generation | matches-generation-staging | +| Firebase Realtime Database | durable-bit-366623-default-rtdb | durable-bit-366623-default-rtdb | f2m-prod | f2m-staging | + +## Auth0 + +| Description | Dev | Test | Prod | Staging | +|-------------|----------------------|----------------------|----------|-------------| +| Tenant | dev-4zf60z3hqoxfjz7m | dev-4zf60z3hqoxfjz7m | prod-f2m | staging-f2m | + +## Postman + +| Description | Dev | Test | Prod | Staging | +|-------------|-------------|--------------|------|-----------------| +| Environment | Dev Cluster | Test Cluster | N/A | Staging Cluster |