Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Challenge Gabriel Dinkel - Cognizant #42

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link href="https://db.onlinewebfonts.com/c/924ee4158324c02e3e0d62e54cafd14f?family=Gotham+Book" rel="stylesheet">
<title>ZoomCare</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
46 changes: 12 additions & 34 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,38 +1,16 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
@import url(https://db.onlinewebfonts.com/c/924ee4158324c02e3e0d62e54cafd14f?family=Gotham+Book);

.App-link {
color: #61dafb;
@font-face {
font-family: "Gotham Book";
src: url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.eot");
src: url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.eot?#iefix")format("embedded-opentype"),
url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.woff2")format("woff2"),
url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.woff")format("woff"),
url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.ttf")format("truetype"),
url("https://db.onlinewebfonts.com/t/924ee4158324c02e3e0d62e54cafd14f.svg#Gotham Book")format("svg");
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
#root {
color: #191E31;
font-family: "Gotham Book";
}
6 changes: 3 additions & 3 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';

test('renders learn react link', () => {
test('renders Appointments App', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
const headerElement = screen.getByText(/Appointments App/i);
expect(headerElement).toBeInTheDocument();
});
32 changes: 11 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
import React from 'react';
import logo from './logo.svg';
import './App.css';
import React, { FC } from "react";
import Appointments from "./pages/Appointments";
import "./App.css";
import Login from "./components/Login";

function App() {
const App: FC = () => {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<>
<h1 style={{ paddingLeft: "24px" }}>Appointments App</h1>
<Login />
<Appointments />
</>
);
}
};

export default App;
25 changes: 25 additions & 0 deletions src/assets/stethoscope.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/components/Appointment.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.appointment-container {
border: 1px solid #a1a1a1;
border-bottom: none;
padding: 20px 24px;
cursor: pointer;
}
.appointment-container:nth-last-child(-n + 1) {
border-bottom: 1px solid #a1a1a1 !important;
}
.appointment-container:hover .container {
transform: translate(-20px, -40px) rotate(-15deg) scale(1.1);
box-shadow: 0 3px 10px rgb(0 0 0 / 0.2);
}
24 changes: 24 additions & 0 deletions src/components/Appointment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { FC } from "react";
import { AppointmentSlot } from "../zoomcare-api";
import ClinicComponent from "./Clinic";
import ProviderComponent from "./Provider";
import Schedule from "./Schedule";
import "./Appointment.css";

const AppointmentComponent: FC<{ appointment: AppointmentSlot }> = ({
appointment,
}) => {
return (
<div className="appointment-container">
<ClinicComponent clinicId={appointment.clinicId} />
<ProviderComponent provider={appointment.provider}>
<Schedule
startTime={appointment.startTime}
durationInMinutes={appointment.durationInMinutes}
/>
</ProviderComponent>
</div>
);
};

export default AppointmentComponent;
10 changes: 10 additions & 0 deletions src/components/Clinic.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
h1 {
color: #293a41;
font-size: 15px;
}
.address {
font-size: 12px;
}
.clinic-container {
padding-bottom: 16px;
}
52 changes: 52 additions & 0 deletions src/components/Clinic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { FC, useEffect, useState, useContext } from "react";
import useFetch from "use-http";
import AuthContext from "../store/auth-context";
import { Clinic } from "../zoomcare-api";
import "./Clinic.css";

const ClinicComponent: FC<{ clinicId: number }> = ({ clinicId }) => {
const ctx = useContext(AuthContext);

const [clinic, setClinic] = useState<Clinic>({
id: 0,
name: "",
address: "",
city: "",
state: "",
zipcode: "",
});
const { get, response, loading, error } = useFetch("api", {
headers: { Authorization: ctx.token },
});

useEffect(() => {
async function loadClinic() {
const clinic = await get(`/clinics/${clinicId}`);
if (response.ok) setClinic(clinic);
}
loadClinic();
}, [clinicId, get, response.ok]);

if (error) {
return null;
}

return (
<>
{loading && "Loading..."}
{clinic.id && (
<div className="clinic-container">
<div>
<h1>{clinic.name}</h1>
</div>
<div className="address">{clinic.address}</div>
<div className="address">
{clinic.city}, {clinic.state} {clinic.zipcode}
</div>
</div>
)}
</>
);
};

export default ClinicComponent;
Empty file added src/components/Login.css
Empty file.
33 changes: 33 additions & 0 deletions src/components/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FC, useEffect, useContext } from "react";
import useFetch from "use-http";
import AuthContext from "../store/auth-context";

const Login: FC = () => {
const ctx = useContext(AuthContext);

const username = "username";
const password = "password";

const { post, response, loading, error } = useFetch("/api");
async function logUser() {
const user = await post("/login", {
username,
password,
});
if (response.ok) {
ctx.onLogin(user.authToken, user.username);
}
}
useEffect(() => {
logUser();
}, []);

return (
<>
{error && "Error!"}
{loading && "Loading..."}
</>
);
};

export default Login;
16 changes: 16 additions & 0 deletions src/components/Provider.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.provider-container {
display: flex;
}
.provider-info {
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 16px;
}
.provider-info h1 {
color: #1cb6e3;
}
.provider-info p {
font-size: 12px;
margin-top: 0;
}
30 changes: 30 additions & 0 deletions src/components/Provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { FC } from "react";
import { Provider } from "../zoomcare-api";
import StethoscopeIcon from "./StethoscopeIcon";
import "./Provider.css";

const ProviderComponent: FC<{ provider: Provider }> = ({
provider,
children,
}) => {
return (
<div className="provider-container">
<div>
<StethoscopeIcon />
</div>
<div id={"provider-" + provider.id} className="provider-info">
<div>
<h1>
{provider.name}, {provider.credentials}
</h1>
</div>
<div>
<p>{provider.phoneNumber}</p>
</div>
<div>{children}</div>
</div>
</div>
);
};

export default ProviderComponent;
15 changes: 15 additions & 0 deletions src/components/Schedule.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.schedule-container {
display: flex;
gap: 10px;
}
.box {
width: 110px;
height: 37px;
background-color: #293a41;
color: #ffffff;
font-weight: bolder;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}
33 changes: 33 additions & 0 deletions src/components/Schedule.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { FC } from "react";
import "./Schedule.css";

type ScheduleData = {
startTime: string;
durationInMinutes: number;
};

const Schedule: FC<ScheduleData> = ({ startTime, durationInMinutes }) => {
const startDate = new Date(startTime.substring(0, 16));
const endDate = new Date(startDate.getTime() + durationInMinutes * 60000);
const formattedStartTime = startDate.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});
const formattedEndTime = endDate.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
});

return (
<div className="schedule-container">
<div className="box">
<span>{formattedStartTime}</span>
</div>
<div className="box">
<span>{formattedEndTime}</span>
</div>
</div>
);
};

export default Schedule;
7 changes: 7 additions & 0 deletions src/components/StethoscopeIcon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.container {
width: 110px;
height: 110px;
padding: 20px 10px 20px 30px;
background-color: #eeeeee;
border-radius: 50%;
}
13 changes: 13 additions & 0 deletions src/components/StethoscopeIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React, { FC } from "react";
import { ReactComponent as StethoscopeSVG } from "../assets/stethoscope.svg";
import "./StethoscopeIcon.css";

const StethoscopeIcon: FC = () => {
return (
<div className="container">
<StethoscopeSVG />
</div>
);
};

export default StethoscopeIcon;
Loading