From 25a67c9683583ba298e0c2a779e0d5b404d23b55 Mon Sep 17 00:00:00 2001 From: Cristi Miloiu Date: Sat, 11 May 2024 19:34:46 +0300 Subject: [PATCH] add clasament & send email in cronometrare platform --- client/src/routes/AllRoutes.tsx | 2 +- client/src/views/Account.view.tsx | 80 ++++++++++++++++---------- client/src/views/Cronometrare.view.tsx | 33 +++++++++++ server/backend.ts | 58 +++++++++++++++++++ server/mailer.ts | 16 +++++- server/prisma/schema.prisma | 1 + 6 files changed, 158 insertions(+), 32 deletions(-) diff --git a/client/src/routes/AllRoutes.tsx b/client/src/routes/AllRoutes.tsx index 0dc81d8..94edc58 100644 --- a/client/src/routes/AllRoutes.tsx +++ b/client/src/routes/AllRoutes.tsx @@ -72,5 +72,5 @@ export const allRoutes = createBrowserRouter([ { path:"cronometrare", element: - } + }, ]); \ No newline at end of file diff --git a/client/src/views/Account.view.tsx b/client/src/views/Account.view.tsx index 666193f..0269f3b 100644 --- a/client/src/views/Account.view.tsx +++ b/client/src/views/Account.view.tsx @@ -1,9 +1,9 @@ -import React, { useState, useEffect } from "react"; -import { useNavigate } from "react-router-dom"; -import { AuthService } from "@genezio/auth"; -import { BackendService } from "@genezio-sdk/apv-production"; -import { Header } from "../components/Header.component"; -import { Helmet } from "react-helmet"; +import React, {useState, useEffect} from "react"; +import {useNavigate} from "react-router-dom"; +import {AuthService} from "@genezio/auth"; +import {BackendService} from "@genezio-sdk/apv-production"; +import {Header} from "../components/Header.component"; +import {Helmet} from "react-helmet"; interface Race { id: number; @@ -30,6 +30,7 @@ const Account: React.FC = () => { const [races, setRaces] = useState([]); const navigate = useNavigate(); const [userPicture, setUserPicture] = useState(""); + const [locOcupat, setLocOcupat] = useState(0); useEffect(() => { const isLoggedIn = async () => { try { @@ -44,8 +45,27 @@ const Account: React.FC = () => { } }; + const takeLocOcupat = async () => { + try { + const response = await BackendService.getAllRaces() + + let locOcupat= 1; + for (let i = 0; i < response.length; i++) { + if (response[i].categorie === races[0].categorie) { + if (response[i].timpAlergat < races[0].timpAlergat) { + locOcupat++; + } + } + } + setLocOcupat(locOcupat); + } catch (error) { + console.log(error); + } + } + isLoggedIn(); - }, [navigate]); + takeLocOcupat(); + }, [navigate,races]); useEffect(() => { const takeRaces = async () => { @@ -65,7 +85,7 @@ const Account: React.FC = () => { APV 2024 | Account -
+

Profil - {userName} @@ -98,29 +118,31 @@ const Account: React.FC = () => {

- - - - - + + + + + + - {races.map((race, index) => ( - - - - - - ))} + {races.map((race, index) => ( + + + + + + + ))}
CategorieNumar TricouTimp Alergat
CategorieNumar TricouTimp AlergatLoc ocupat
- {racesContext[race.categorie]} - - {race.numarTricou ? race.numarTricou : "N/A"} - - {race.timpAlergat ? race.timpAlergat : "N/A"} -
+ {racesContext[race.categorie]} + + {race.numarTricou ? race.numarTricou : "N/A"} + + {race.timpAlergat ? race.timpAlergat : "N/A"} + {locOcupat===0 || race.timpAlergat === null || race.timpAlergat === "00:00:00" ? "N/A" : locOcupat}
diff --git a/client/src/views/Cronometrare.view.tsx b/client/src/views/Cronometrare.view.tsx index fceeba6..39bd9d6 100644 --- a/client/src/views/Cronometrare.view.tsx +++ b/client/src/views/Cronometrare.view.tsx @@ -178,6 +178,7 @@ const Cronometrare: React.FC = () => { Update + Send email @@ -261,6 +262,38 @@ const Cronometrare: React.FC = () => { className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded" /> + + { + formDataList[index].emailTrimis === "DA" ? ( + + ) : ( + { + const sendEmail = async () => { + try { + const response = await BackendService.sendRaceCompletionEmail( + formDataList[index].id) + if (response) { + alert(response.message) + window.location.reload(); + } + } catch (error) { + console.log(error); + alert("Error sending email"); + } + }; + sendEmail(); + }} + className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" + />)} + ))} diff --git a/server/backend.ts b/server/backend.ts index 46ee7b0..2399af1 100644 --- a/server/backend.ts +++ b/server/backend.ts @@ -509,4 +509,62 @@ export class BackendService { return createHTTPError(500, "Internal Server Error"); } } + + @GenezioAuth() + async sendRaceCompletionEmail(context: GnzContext, id: number) { + const userInfo = await this.prisma.cursa.findUnique({ + where: { + id: id + } + }) + if (!userInfo) { + throw createHTTPError(404, "User not exist"); + } + const subject = `Felicitări pentru finalizarea cursei - Aleargă pentru Viață`; + const ora = userInfo.timpAlergat; + const cursa = userInfo.categorie; + const aiTrimis = userInfo.emailTrimis; + const name = userInfo.name; + + if(aiTrimis === "DA"){ + return { + status: 200, + message: "A fost trimis deja email-ul" + } + } + + + const userId = userInfo.userId; + const user = await pool.query(`SELECT "email" FROM "users" WHERE "userId" = $1`, [userId]); + if (user.rows[0] === undefined) { + throw createHTTPError(404, "User not exist"); + } + + const email = user.rows[0].email; + + const response = await this.mailer.sendRaceCompletionEmail( + email, + subject, + name!, + cursa!, + ora! + ); + + if(response){ + await this.prisma.cursa.update({ + where: { + id: id + }, + data: { + emailTrimis: "DA" + } + }); + return { + status: 200, + message: "Successfully sent" + } + } else { + return createHTTPError(500, "Internal Server Error"); + } + } } diff --git a/server/mailer.ts b/server/mailer.ts index 2082cd7..c2d96b0 100644 --- a/server/mailer.ts +++ b/server/mailer.ts @@ -87,6 +87,18 @@ export class Mailer{ cursa: string, minuteAlergate: string ){ + const races = { + "0": "Cursa Copii", + "1": "Feminin 13-17 ani", + "2": "Masculin 13-17 ani", + "3": "Feminin 18-35 de ani", + "4": "Masculin 18-35 de ani", + "5": "Feminin 35+ de ani", + "6": "Masculin 35+ de ani", + "7": "Nu a selectat" + }; + // @ts-expect-error: cursa is a + const cursaText = races[cursa]; const html = ` @@ -102,9 +114,9 @@ export class Mailer{ Logo Aleargă pentru Viață

Felicitari, ${nume}!

-

Detalii ${cursa}, ediția a XV-a!

+

Detalii ${cursaText}, ediția a XV-a!

-

Ai terminat ${cursa} în ${minuteAlergate} de minute!

+

Ai terminat ${cursaText} în ${minuteAlergate} de minute!

Iti multumim ca ai alergat alaturi de noi pentru o cauză nobilă!

Cu drag,

diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index 95a888a..3e79a6b 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -38,6 +38,7 @@ model Cursa { suma String? checkin String? inscriereFizic String? + emailTrimis String? } // exemple de user si curse: