Skip to content

Commit

Permalink
Merge pull request #24 from TritonSE/16-proposal-solution-component
Browse files Browse the repository at this point in the history
Proposal Solution Component
  • Loading branch information
soma-p authored Feb 10, 2025
2 parents 564fe4d + 206077e commit 79a2ee2
Show file tree
Hide file tree
Showing 20 changed files with 700 additions and 9 deletions.
40 changes: 40 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"@react-pdf/renderer": "^3.4.4",
"@testing-library/jest-dom": "^6.1.4",
"@testing-library/react": "^14.1.2",
"chart.js": "^4.4.7",
"chartjs-plugin-datalabels": "^2.2.0",
"draft-js": "^0.11.7",
"draftjs-to-html": "^0.9.1",
"email-validator": "^2.0.4",
Expand All @@ -35,6 +37,7 @@
"moment": "^2.30.1",
"next": "^14.2.3",
"react": "^18",
"react-chartjs-2": "^5.3.0",
"react-dom": "^18",
"react-draft-wysiwyg": "^1.15.0",
"react-hook-form": "^7.49.3",
Expand Down
Binary file added frontend/public/accesible_clinics.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/affordable_surgeries.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/solution_main.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/public/solution_vector.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 6 additions & 2 deletions frontend/src/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
/* :root {
@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;600;700&family=Montserrat:wght@300;400;600;700;900&display=swap");

:root {
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono",
"Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono",
"Courier New", monospace;
--font-open-sans: "Open Sans", sans-serif;
--font-montserrat: "Montserrat", sans-serif;
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
Expand Down Expand Up @@ -84,4 +88,4 @@ a {
html {
color-scheme: dark;
}
} */
}
7 changes: 1 addition & 6 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { Inter } from "next/font/google";

import type { Metadata } from "next";

import "@/app/globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Solution from "../components/solution/Solution";
export default function Home() {
return (
<main>
Expand All @@ -11,7 +12,7 @@ export default function Home() {
<p>Problem Statement&nbsp;</p>
</div>
<div>
<p>Solution&nbsp;</p>
<Solution />
</div>
<div>
<p>Community Support&nbsp;</p>
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/components/solution/AccesibleClinics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";

import styles from "@/components/solution/accesibleClinics.module.css";

const AccesibleClinic: React.FC = () => {
return (
<div className={styles.outerContainer}>
<div className={styles.innerContainer}>
<div className={styles.imageSection}>
<img className={styles.image} alt="Accessible Clinics" src="/accesible_clinics.png" />
</div>
<div className={styles.textSection}>
<h2 className={styles.heading}>Accessible Clinics</h2>
<p className={styles.description}>
By strategically placing 10 clinics across the city of LA, pet owners no longer have to
experience long drives during rush hour traffic with a frightened pet.
</p>
<p className={styles.description}>
{" "}
Additionally, clinics will offer <strong>free transport vans</strong> for clients
without private transportation.
</p>
</div>
</div>
</div>
);
};

export default AccesibleClinic;
32 changes: 32 additions & 0 deletions frontend/src/components/solution/AffordableSurgeries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from "react";

import styles from "@/components/solution/affordableSuergies.module.css";

const AffordableSurgeries: React.FC = () => {
return (
<div className={styles.outerContainer}>
<div className={styles.innerContainer}>
<div className={styles.textSection}>
<h2 className={styles.heading}>Affordable Surgeries</h2>
<p className={styles.description}>
Currently, procedures can range from $400 to $900. By adopting a high volume, low cost
business model, Spay.LA can bring procedures prices down to just $50.
</p>
<p className={styles.description}>
Additionally, we will offer a <strong>voucher program</strong> for low income families
and their pets.
</p>
</div>
<div className={styles.imageSection}>
<img
className={styles.image}
alt="Affordable Surgeries"
src="/affordable_surgeries.png"
></img>
</div>
</div>
</div>
);
};

export default AffordableSurgeries;
149 changes: 149 additions & 0 deletions frontend/src/components/solution/Appointments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
"use client";

import {
BarElement,
CategoryScale,
Chart,
ChartOptions,
Legend,
LinearScale,
Title,
Tooltip,
} from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import React, { useEffect, useRef, useState } from "react";
import { Bar } from "react-chartjs-2";

import styles from "@/components/solution/appointments.module.css";

Chart.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend, ChartDataLabels);

const Appointments: React.FC = () => {
const data = {
labels: [
["Other", "Clinics"],
["Spay.LA", "Clinics"],
],
datasets: [
{
label: "Dataset 1",
data: [11520, 28000],
backgroundColor: ["#2D5177", "#ff8359"],
borderColor: ["#2D5177", "#ff8359"],
borderWidth: 1,
barThickness: 80,
},
],
};

const options: ChartOptions<"bar"> = {
maintainAspectRatio: false,
layout: {
padding: {
top: 75,
},
},
animations: {
y: {
type: "number",
duration: 2000,
easing: "easeOutCubic", // Smooth acceleration & deceleration
},
},
plugins: {
tooltip: {
enabled: false,
},
legend: {
display: false,
},
datalabels: {
anchor: "end",
align: "top",
offset: 5,
color: ["#2D5177", "#ff8359"],
font: {
size: 24,
weight: "bold",
family: "Montserrat",
},
formatter: (value: number) => value.toLocaleString(), // Format numbers with commas
},
},
scales: {
x: {
grid: {
drawOnChartArea: false,
},
ticks: {
color: "black",
font: {
size: 20,
family: "Montserrat",
},
},
},
y: {
grid: {
display: false,
},
display: false,
beginAtZero: true,
},
},
};

const chartRef = useRef<HTMLDivElement | null>(null);
const [chartKey, setChartKey] = useState(0);
const [hasAnimated, setHasAnimated] = useState(false); // Track if animation has occurred

useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setChartKey((prevKey) => prevKey + 1); // Forces chart re-render
setHasAnimated(true); // Mark animation as done
observer.unobserve(entry.target); // Stop observing after animation
}
});
},
{ threshold: 0.5 }, // Trigger when 50% of the chart is visible
);

if (chartRef.current) {
observer.observe(chartRef.current);
}

return () => {
if (chartRef.current) {
observer.unobserve(chartRef.current);
}
};
}, [hasAnimated]);

return (
<div className={styles.outerContainer}>
<div className={styles.innerContainer}>
<div className={styles.textSection}>
<h2 className={styles.heading}>Available Appointments</h2>
<p className={styles.description}>
By operating 5 days a week with day and night shifts,
<br /> Spay.LA can perform almost
<span style={{ fontWeight: "bold" }}> triple the surgeries</span> of <br /> other
clinics in LA.
<br />
<br />
This means more surgeries and less time waiting for <br /> an available appointment.
</p>
</div>
<div ref={chartRef} className={styles.graphSection}>
<p className={styles.graphTitle}>Surgeries Per Year</p>
<Bar key={chartKey} data={data} options={options} />
</div>
</div>
</div>
);
};

export default Appointments;
Loading

0 comments on commit 79a2ee2

Please sign in to comment.