Skip to content

Commit

Permalink
feat: redone migrations and reenabled register form (#53)
Browse files Browse the repository at this point in the history
* feat: redone migrations and reenabled register form

* fix: fk in participants

* fix: project output config option

* feat: update the number and  value of payment as joining the team

* feat: added collumn created_by to teams

* feat: migration to create bucket auto

* feat: added email sent to the owner of team to alert a new member of team and remind the payment

* feat: added a check to verify if the team as already paid

* feat: modals of information to participants

* fix: removed lucide-react and used svgs

* feat: improved messages

* feat: synced config with remote database

* feat: change mail client

* chore: change env names

* chore: change envs again

* feat: removed check box

* fix: same email could enter/create in teams multiple times

* feat: added email of new member in new member notify

---------

Co-authored-by: João Lobo <[email protected]>
  • Loading branch information
FilipeR13 and joaodiaslobo authored Feb 20, 2025
1 parent 25e0067 commit d15276d
Show file tree
Hide file tree
Showing 24 changed files with 455 additions and 255 deletions.
8 changes: 3 additions & 5 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ SUPABASE_URL=<SUPABASE URL>
SUPABASE_ANON_KEY=<SUPERBASE ANON KEY>
SENDER_EMAIL=<EMAIL USED FOR AUTOMATIC EMAILS>
DISCORD_INVITE=<DISCORD SERVER INVITE LINK>
SES_REGION=<REGION OF YOU SES CONFIG>
SMTP_USER=<YOUR SMTP USER>
SMTP_PASS=<YOUR SMTP PASSWORD>
SMTP_HOST=<YOUR SMTP HOST>
PUBLIC_BLOCKED_URLS=<BLOCKED URL's SEPARATED BY COMMAS>
SES_REGION=<AWS REGION>
SES_ACCESS=<AWS ACCESS KEY>
SES_SECRET=<AWS SECRET ACCESS KEY>
PUBLIC_HOST_URL=<YOUR HOST URL>
2 changes: 1 addition & 1 deletion astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ import netlify from "@astrojs/netlify";
export default defineConfig({
site: import.meta.env.PUBLIC_HOST_URL,
integrations: [tailwind(), icon(), react()],
output: "static",
output: "server",
adapter: netlify(),
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
"dependencies": {
"@astrojs/netlify": "^5.1.3",
"@astrojs/react": "^3.0.10",
"@aws-sdk/client-ses": "^3.750.0",
"@fontsource-variable/inter": "^5.0.16",
"@headlessui/react": "^1.7.18",
"@heroicons/react": "^2.1.1",
"@supabase/supabase-js": "^2.39.6",
"@types/react": "^18.2.58",
"@types/react-dom": "^18.2.19",
"emailjs": "^4.0.3",
"flowbite": "^2.3.0",
"heroicons": "^2.1.1",
"micromodal": "^0.4.10",
Expand Down
5 changes: 3 additions & 2 deletions src/components/confirmationModal.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function ConfirmationModal({ placeHolder, closeModal }) {
export default function ConfirmationModal({ title, content, closeModal }) {
return (
<div className="fixed inset-0 bg-gray-800 bg-opacity-75 flex justify-center items-center">
<div className="relative bg-black border-2 border-gray-500 rounded-lg shadow-lg">
Expand All @@ -18,7 +18,8 @@ export default function ConfirmationModal({ placeHolder, closeModal }) {
d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
/>
</svg>
<h3 className="mb-5 text-lg font-normal text-white">{placeHolder}</h3>
<h3 className="mb-5 text-lg font-normal text-white">{title}</h3>
<p className="text-white mb-5">{content}</p>
<button
className="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center"
type="submit"
Expand Down
12 changes: 9 additions & 3 deletions src/components/header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ const headerClass = sticky
))
}
<li>
<button
<a
href="/register"
type="button"
class="rounded-full px-2.5 py-1 text-xs font-semibold text-white shadow-sm ring-1 ring-inset ring-white cursor-not-allowed"
>Register</button
class="rounded-full px-2.5 py-1 text-xs font-semibold text-white shadow-sm ring-1 ring-inset ring-white hover:ring-secondary"
>Register</a
>
</li>
</ul>
Expand Down Expand Up @@ -71,6 +72,11 @@ const headerClass = sticky
</a>
<nav>
<ul class="flex flex-col">
<li>
<a class="block py-4 text-center text-xl" href="/register">
Register
</a>
</li>
{
navItems.map(({ title, url }) => (
<li>
Expand Down
36 changes: 36 additions & 0 deletions src/components/informationModal.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export default function InformationModal({ title, content, closeModal }) {
return (
<div className="fixed inset-0 bg-gray-800 bg-opacity-75 flex justify-center items-center">
<div className="relative bg-black border-2 border-gray-500 rounded-lg shadow-lg">
<div className="p-4 md:p-5 text-center">
<div className="flex justify-center mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-circle-check-big text-center text-green-500 h-12 w-12"
>
<path d="M21.801 10A10 10 0 1 1 17 3.335" />
<path d="m9 11 3 3L22 4" />
</svg>
</div>
<h3 className="mb-5 text-lg font-normal text-white">{title}</h3>
<p className="text-white mb-5">{content}</p>
<button
onClick={closeModal}
className="py-2.5 px-5 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary"
type="button"
>
Close
</button>
</div>
</div>
</div>
);
}
75 changes: 40 additions & 35 deletions src/components/registerForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FileUpload from "~/components/forms/fileUpload.jsx";
import ToggleButton from "~/components/forms/toggleButton.jsx";
import Button from "~/components/button.jsx";
import ConfirmationModal from "~/components/confirmationModal.jsx";
import InformationModal from "~/components/informationModal.jsx";
import FormsTemplate from "./forms/formsTemplate.jsx";
import ErrorBox from "~/components/forms/errorBox.jsx";
import { useState } from "react";
Expand All @@ -15,11 +16,12 @@ import universities from "~/data/institutes.json";
export default function Form() {
const [responseErrors, setResponseErrors] = useState("");
const [loadingState, setLoadingState] = useState(false);
const [showModal, setShowModal] = useState(false);
const [showConfirmationModal, setShowConfirmationModal] = useState(false);
const [showInformationModal, setShowInformationModal] = useState(false);

async function submit(e) {
e.preventDefault();
closeModal();
closeConfirmationModal();
setLoadingState(true);
const formData = new FormData(e.target);
const response = await fetch("/api/register", {
Expand All @@ -32,16 +34,29 @@ export default function Form() {
setResponseErrors(data.message.errors);
setLoadingState(false);
} else {
window.location.href = "/";
openInformationModal();
}
}

function openModal() {
setShowModal(true);
function goBack() {
closeInformationModal();
window.location.href = "/";
}

function closeModal() {
setShowModal(false);
function openConfirmationModal() {
setShowConfirmationModal(true);
}

function closeConfirmationModal() {
setShowConfirmationModal(false);
}

function openInformationModal() {
setShowInformationModal(true);
}

function closeInformationModal() {
setShowInformationModal(false);
}

return (
Expand Down Expand Up @@ -103,39 +118,29 @@ export default function Form() {
{responseErrors.length > 0 && (
<ErrorBox responseErrors={responseErrors} />
)}

<div className="flex items-center mb-5">
<div className="flex items-center h-5">
<input
id="terms"
type="checkbox"
value=""
className="w-4 h-4 border border-gray-300 text-primary rounded bg-gray-50 focus:ring-3 focus:ring-primary"
required
/>
</div>
<label
htmlFor="terms"
className="ms-2 text-sm font-medium text-white "
>
I agree with the{" "}
<a
href="/docs/regulation.pdf"
className="text-primary hover:underline"
>
event regulations
</a>
</label>
</div>
<Button
loadingState={loadingState}
placeholder="Submit"
onClick={openModal}
onClick={openConfirmationModal}
/>
{showModal && (
{showConfirmationModal && (
<ConfirmationModal
placeHolder="Are you sure you want to submit?"
closeModal={closeModal}
title="Are you sure you want to submit?"
closeModal={closeConfirmationModal}
/>
)}
{showInformationModal && (
<InformationModal
title="You're registered!"
content={
<>
Your registration was successful! We've sent you an email with
your confirmation code. <br />
Head over to the teams page to create your own team or join a
team with your partners.
</>
}
closeModal={goBack}
/>
)}
</form>
Expand Down
60 changes: 49 additions & 11 deletions src/components/teamFormation/createTeam.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { useState } from "react";
import TextInput from "~/components/forms/textInput.jsx";
import ConfirmationModal from "~/components/confirmationModal.jsx";
import InformationModal from "~/components/informationModal.jsx";
import Button from "~/components/button.jsx";

export default function CreateTeam() {
const [responseErrors, setResponseErrors] = useState("");
const [showModal, setShowModal] = useState(false);
const [showConfirmationModal, setShowConfirmationModal] = useState(false);
const [showInformationModal, setShowInformationModal] = useState(false);
const [loadingState, setLoadingState] = useState(false);

async function submit(e) {
e.preventDefault();
closeModal();
closeConfirmationModal();
setLoadingState(true);
const formData = new FormData(e.target);
const response = await fetch("/api/teams/create", {
Expand All @@ -23,16 +25,29 @@ export default function CreateTeam() {
setResponseErrors(data.message.errors);
setLoadingState(false);
} else {
window.location.href = "/";
openInformationModal();
}
}

function openModal() {
setShowModal(true);
function goBack() {
closeInformationModal();
window.location.href = "/";
}

function closeModal() {
setShowModal(false);
function openConfirmationModal() {
setShowConfirmationModal(true);
}

function closeConfirmationModal() {
setShowConfirmationModal(false);
}

function openInformationModal() {
setShowInformationModal(true);
}

function closeInformationModal() {
setShowInformationModal(false);
}

return (
Expand Down Expand Up @@ -97,12 +112,35 @@ export default function CreateTeam() {
<Button
loadingState={loadingState}
placeholder="Create"
onClick={openModal}
onClick={openConfirmationModal}
/>
{showModal && (
{showConfirmationModal && (
<ConfirmationModal
placeHolder="Are you sure you want to create this team?"
closeModal={closeModal}
title="Are you sure you want to create this team?"
content={
<>
The cost of the participation is 2€ per person in the team, to
a maximum of 5 people. <br />
When your team is complete, go to the CeSIUM room (DI 1.04) to
make the payment.
</>
}
closeModal={closeConfirmationModal}
/>
)}
{showInformationModal && (
<InformationModal
title="Team created!"
content={
<>
Your team was successfully created! <br />
We sent you an email with the confirmation code related to
your team.
<br />
Share this code with your teammates so they can join the team.
</>
}
closeModal={goBack}
/>
)}
</form>
Expand Down
Loading

0 comments on commit d15276d

Please sign in to comment.