Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
anthonyhardman committed Sep 14, 2023
2 parents 84c9a7a + 0651d9a commit 1468a44
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/v2/client/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="custom-modal-portal"></div>
<div id="root"></div>
<!--
This HTML file is a template.
Expand Down
2 changes: 2 additions & 0 deletions src/v2/client/src/AppRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Toaster } from "react-hot-toast"
import { Route, Routes } from "react-router-dom"
import { Home } from "./pages/home/Home"
import { NavBar } from "./components/NavBar"

export const AppRoutes = () => {

return (
<>
<div className="justify-content-center">
<Toaster />
<NavBar />
<Routes>
<Route path="/" element={<Home />} />
</Routes>
Expand Down
4 changes: 4 additions & 0 deletions src/v2/client/src/assets/custom.scss
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
$primary: #673AB7;
$secondary: #FFA500;
$info: #0089DB;

@import "../../node_modules/bootstrap/scss/bootstrap.scss"
131 changes: 131 additions & 0 deletions src/v2/client/src/components/CustomModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { Modal } from "bootstrap";
import React, { FC, useEffect, useState } from "react"; import { createPortal } from "react-dom";

export interface CustomModalControls {
hide: () => void;
show: () => void;
sizeClass: string;
id: string;
label: string;
isHidden: () => boolean;
}

export const useModal = (
label: string,
size: string = "notincludedanywhere"
): CustomModalControls => {
const random = (Math.random() + 1).toString(36).substring(7);
const [id, _setId] = useState(
`custoModalLabel${label
.replaceAll(" ", "")
.replace(/[^\w\s']|_/g, "")}${random}`
);
const validSizes = [
"sm",
"lg",
"xl",
"fullscreen",
"fullscreen-sm-down",
"fullscreen-md-down",
"fullscreen-lg-down",
"fullscreen-xl-down",
"fullscreen-xxl-down",
];
const sizeClass = size.includes("fullscreen")
? validSizes.includes(size)
? `modal-xl modal-${size}`
: ``
: validSizes.includes(size)
? `modal-${size}`
: ``;

const hide = () => {
const modalElement = document.getElementById(id);
if (modalElement) {
const modal = Modal.getInstance(modalElement);
if (modal) {
modal.hide();
}
}
};
const show = () => {
const modalElement = document.getElementById(id);
if (modalElement) {
const modal = new Modal(modalElement);
if (modal) {
modal.show();
}
}
};

const isHidden = () => {
const modal = document.getElementById(id);
return !modal?.style.display;
};
return { hide, show, sizeClass, id, label, isHidden };
};

export type ModalButton = FC<{
showModal: () => void;
}>;

export const CustomModal: FC<{
controls: CustomModalControls;
ModalButton?: ModalButton;
dismissible?: boolean
onClose?: () => void;
onShow?: () => void;
children: React.ReactNode;
}> = ({ controls, ModalButton, dismissible = true, onClose, onShow, children }) => {
useEffect(() => {
const customModalElement = document.getElementById(controls.id);
const listener = () => {
if (onShow) onShow();
};
if (customModalElement) {
customModalElement.addEventListener("shown.bs.modal", listener);
}
return () =>
customModalElement?.removeEventListener("show.bs.modal", listener);
}, [controls.id, onShow]);

useEffect(() => {
const customModalElement = document.getElementById(controls.id);
const listener = () => {
if (onClose) onClose();
};
if (customModalElement) {
customModalElement.addEventListener("hidden.bs.modal", listener);
}
return () =>
customModalElement?.removeEventListener("hidden.bs.modal", listener);
}, [controls.id, onClose]);

const portalElement = document.querySelector("#custom-modal-portal");

return (
<>
{ModalButton ? (
<ModalButton showModal={controls.show} />
) : (
<button className="btn btn-bold w-100 " onClick={controls.show}>
{controls.label}
</button>
)}
{portalElement &&
createPortal(
<div className="modal fade" data-bs-backdrop={dismissible ? "true" : "static"} id={controls.id} tabIndex={-1}>
<div
className={
`modal-dialog modal-dialog-centered modal-dialog-scrollable ` +
controls.sizeClass
}
>
<div className="modal-content">{children}</div>
</div>
</div>,
portalElement
)}
</>
);
};
33 changes: 33 additions & 0 deletions src/v2/client/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Link } from "react-router-dom"

export const NavBar = () => {
return (
<nav className="navbar navbar-expand-md navbar-light bg-primary shadow-lg">
<div className="container-fluid">
<a className="navbar-brand text-white fw-bold" href="https://sanpetepantry.org/" target="_blank" rel="noreferrer">
Sanpete Food Bank
</a>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav me-auto mb-2 mb-md-0">
<li className="nav-item my-auto border-start border-white px-2">
<Link to={"/"} className="text-white text-decoration-none">Home</Link>
</li>
<li className="nav-item my-auto border-start border-white px-2">
<Link to={"/"} className="text-white text-decoration-none">Donate</Link>
</li>
<li className="nav-item my-auto border-start border-white px-2">
<Link to={"/"} className="text-white text-decoration-none">Teams</Link>
</li>
<li className="nav-item my-auto border-start border-white px-2">
<Link to={"/"} className="text-white text-decoration-none">Swagger</Link>
</li>
</ul>
<button className="btn btn-secondary shadow text-white">LOGOUT</button>
</div>
</div>
</nav>
)
}
32 changes: 32 additions & 0 deletions src/v2/client/src/pages/home/BenefitsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useModal, CustomModal, ModalButton } from "../../components/CustomModal"

export const BenefitsModal = () => {
const eventDetailModalControl = useModal("Benefits", "lg")

const ModalButton: ModalButton = ({ showModal }) => (
<button className="btn text-info"
onClick={showModal}>BENEFITS OF CHARITY TEAMS</button>
)
return (
<CustomModal ModalButton={ModalButton} controls={eventDetailModalControl}>
<>
<div className="modal-header">
<div className="modal-title fw-bold fs-4">Benefits of Joining a Charity Event Team</div>
</div>
<div className="modal-body">
<ul>
<li>Joining a team for a charity event is a powerful way to maximize your impact and make a positive difference in the lives of others.</li>
<li>When you're part of a team, you benefit from the camaraderie and collective motivation, which encourages you to contribute more generously than you might on your own.</li>
<li>The spirit of friendly competition among teams drives each member to push their limits, resulting in a greater overall contribution to the cause.</li>
<li>Being part of a team fosters a sense of belonging, creating a network of passionate individuals united by a common goal.</li>
<li>By working together and leveraging each other's strengths, you not only raise more funds for the charity, but you also forge lasting connections that strengthen your community and promote a culture of giving.</li>
</ul>
<div className="row mx-5 my-3">
<button className="btn text-info"
onClick={() => eventDetailModalControl.hide()}>CLOSE</button>
</div>
</div>
</>
</CustomModal>
)
}
51 changes: 50 additions & 1 deletion src/v2/client/src/pages/home/Home.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,55 @@
import { BenefitsModal } from "./BenefitsModal";
import { UpcomingEventsModal } from "./UpcomingEventsModal";

export const Home = () => {
const width = 1;
return (
<div className="btn btn-primary">Hello World!</div>
<div className="container mt-3 text-center">
<div className="bg-primary shadow text-white ">
<h3>There are currently no upcoming events</h3>
<iframe
data-testid={"homePageVideo"} id={"homePageVideo"}
src="https://www.youtube.com/embed/wkFlIx9sV04"
title="YouTube video player"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
height="450"
style={{ width: "100%" }}
allowFullScreen />
<div className="fs-5"><span className="fw-bold">0%</span> of our $0 goal</div>
<div className="row">
<div className="col-6 offset-3">
<div className="progress bg-success-subtle">
<div className="progress-bar bg-success" style={{ width: width + "%" }} role="progressbar" aria-valuenow={width} aria-valuemin={1} aria-valuemax={100} />
</div>
</div>
</div>
<div className="row py-3">
<div className="col-5 text-end">
<button className="btn btn-secondary text-white">SHARE NOW</button>
</div>
<div className="col-auto">
<UpcomingEventsModal />
</div>
<div className="col-auto">
<button className="btn btn-secondary text-white">DONATE</button>
</div>
</div>
</div>
<div className="bg-light shadow px-3">
<div className="fw-bold text-black fs-4">Charity Teams</div>
<div className="text-start">Joining a charity team is a fulfilling way to make a positive impact while connecting with like-minded individuals who share your passion for giving back.</div>
<div className="my-3">
<BenefitsModal />
</div>
<div className="row pb-3">
<div className="col text-end">
<button className="btn btn-secondary text-white">ACTIVE TEAMS</button>
</div>
<div className="col text-start">
<button className="btn btn-secondary text-white">CREATE A TEAM</button>
</div>
</div>
</div>
</div>
)
}
21 changes: 21 additions & 0 deletions src/v2/client/src/pages/home/UpcomingEventsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CustomModal, useModal, ModalButton } from "../../components/CustomModal"

export const UpcomingEventsModal = () => {
const eventDetailModalControl = useModal("Event Details", "lg")

const ModalButton: ModalButton = ({ showModal }) => (
<button className="btn btn-secondary text-white"
onClick={showModal}>EVENT DETAILS</button>
)
return (
<CustomModal ModalButton={ModalButton} controls={eventDetailModalControl}>
<div className="modal-body text-center">
<div className="fw-bold fs-3">Event: There are currently no upcoming events</div>
<div className="row mx-5 my-3">
<button className="btn btn-secondary text-white"
onClick={() => eventDetailModalControl.hide()}>OK</button>
</div>
</div>
</CustomModal>
)
}

0 comments on commit 1468a44

Please sign in to comment.