diff --git a/package-lock.json b/package-lock.json index 15a7649..5b82280 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,10 +11,16 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.7", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-scripts": "5.0.1", + "react-router": "^6.26.2", + "react-router-dom": "^6.26.2", + "react-scripts": "^5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "tailwindcss": "^3.4.13" } }, "node_modules/@adobe/css-tools": { @@ -3540,6 +3546,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz", + "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -5811,6 +5825,29 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", @@ -15829,6 +15866,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/psl": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", @@ -16215,11 +16257,40 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz", + "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==", + "dependencies": { + "@remix-run/router": "1.19.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz", + "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==", + "dependencies": { + "@remix-run/router": "1.19.2", + "react-router": "6.26.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", - "license": "MIT", "dependencies": { "@babel/core": "^7.16.0", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", @@ -18020,10 +18091,9 @@ "license": "MIT" }, "node_modules/tailwindcss": { - "version": "3.4.12", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.12.tgz", - "integrity": "sha512-Htf/gHj2+soPb9UayUNci/Ja3d8pTmu9ONTfh4QY8r3MATTZOzmv6UYWF7ZwikEIC8okpfqmGqrmDehua8mF8w==", - "license": "MIT", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz", + "integrity": "sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==", "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", diff --git a/package.json b/package.json index 00efdfe..f9530dd 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,12 @@ "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "axios": "^1.7.7", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-scripts": "5.0.1", + "react-router": "^6.26.2", + "react-router-dom": "^6.26.2", + "react-scripts": "^5.0.1", "web-vitals": "^2.1.4" }, "scripts": { @@ -34,5 +37,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "tailwindcss": "^3.4.13" } } diff --git a/public/index.html b/public/index.html index aa069f2..ef614e2 100644 --- a/public/index.html +++ b/public/index.html @@ -1,43 +1,12 @@ - - - - - - - - - - - React App - - - -
- - + + + + + MCDonalds + + +
+ diff --git a/public/manifest.json b/public/manifest.json index 080d6c7..04f5b4f 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,21 +1,11 @@ { - "short_name": "React App", - "name": "Create React App Sample", + "short_name": "", + "name": "", "icons": [ { - "src": "favicon.ico", + "src": "", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" } ], "start_url": ".", diff --git a/src/Assets/CSS/Navbar.min.css b/src/Assets/CSS/Navbar.min.css new file mode 100644 index 0000000..0e0b046 --- /dev/null +++ b/src/Assets/CSS/Navbar.min.css @@ -0,0 +1,5 @@ +@import url(https://fonts.bunny.net/css?family=abril-fatface:400|rubik:600,800i,900i); + +body { + background-color: #101725; +} diff --git a/src/Assets/CSS/input.css b/src/Assets/CSS/input.css new file mode 100644 index 0000000..bd6213e --- /dev/null +++ b/src/Assets/CSS/input.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/src/Components/Layout.jsx b/src/Components/Layout.jsx new file mode 100644 index 0000000..43bc9d2 --- /dev/null +++ b/src/Components/Layout.jsx @@ -0,0 +1,14 @@ +import React from "react"; +import { Outlet } from "react-router-dom"; +import Navbar from "./Navbar"; + +const Layout = () => { + return ( + <> + + + + ); +}; + +export default Layout; diff --git a/src/Components/Navbar.jsx b/src/Components/Navbar.jsx new file mode 100644 index 0000000..c717017 --- /dev/null +++ b/src/Components/Navbar.jsx @@ -0,0 +1,66 @@ +import React, { useState, useEffect, useRef } from "react"; +import { Link } from "react-router-dom"; +import "../Assets/CSS/Navbar.min.css"; + +function Navbar() { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const dropdownRef = useRef(null); + + const handleDropdownToggle = (event) => { + event.stopPropagation(); + setIsDropdownOpen(!isDropdownOpen); + }; + + const handleOptionClick = () => { + setIsDropdownOpen(false); + }; + + const handleClickOutsideDropdown = (event) => { + if (dropdownRef.current && !dropdownRef.current.contains(event.target)) { + setIsDropdownOpen(false); + } + }; + + useEffect(() => { + window.addEventListener("click", handleClickOutsideDropdown); + + return () => { + window.removeEventListener("click", handleClickOutsideDropdown); + }; + }, []); + + return ( + + ); +} + +export default Navbar; diff --git a/src/Components/Preloader.jsx b/src/Components/Preloader.jsx new file mode 100644 index 0000000..20207f0 --- /dev/null +++ b/src/Components/Preloader.jsx @@ -0,0 +1,11 @@ +import React from "react"; + +const Preloader = () => { + return ( +
+
+
+ ); +}; + +export default Preloader; diff --git a/src/Pages/Home.jsx b/src/Pages/Home.jsx new file mode 100644 index 0000000..c479b2a --- /dev/null +++ b/src/Pages/Home.jsx @@ -0,0 +1,12 @@ +import React from "react"; +import "../Assets/CSS/input.css"; + +function Home() { + return ( +
+

Hi

+
+ ); +} + +export default Home; diff --git a/src/Pages/Login.jsx b/src/Pages/Login.jsx new file mode 100644 index 0000000..46f037a --- /dev/null +++ b/src/Pages/Login.jsx @@ -0,0 +1,62 @@ +import React, { useState } from 'react'; + +const Login = () => { + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const handleLogin = (e) => { + e.preventDefault(); + // Login logic here + console.log('Email:', email); + console.log('Password:', password); + }; + + return ( +
+
+

McDonald's Work Schedule

+
+
+
+ + setEmail(e.target.value)} + required + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-highlightRed focus:border-highlightRed" + placeholder="Email address" + /> +
+
+ + setPassword(e.target.value)} + required + className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-highlightRed focus:border-highlightRed" + placeholder="Password" + /> +
+
+ +
+ +
+
+
+
+ ); +}; + +export default Login; diff --git a/src/Pages/Scheduleinfo.jsx b/src/Pages/Scheduleinfo.jsx new file mode 100644 index 0000000..4f701e5 --- /dev/null +++ b/src/Pages/Scheduleinfo.jsx @@ -0,0 +1,68 @@ +import React, { useEffect, useState } from 'react'; +import axios from 'axios'; + +const WorkSchedule = () => { + const [schedule, setSchedule] = useState([]); + const [error, setError] = useState(false); // State to track if there's an error + + useEffect(() => { + const fetchSchedule = async () => { + try { + const response = await axios.get('http://localhost:5000/api/schedules'); + setSchedule(response.data); + setError(false); // Reset error state if the fetch succeeds + } catch (error) { + console.error('Error fetching the schedule data:', error); + setError(true); // Set error to true if the fetch fails + } + }; + + fetchSchedule(); + }, []); + + return ( +
+
+

Employee Work Schedule

+ + + + + + + + + + + + + + + {error ? ( + // Display this row if fetching data fails + + + + ) : ( + // Display table rows if data fetching is successful + schedule.map((person, index) => ( + + + + + + + + + + + )) + )} + +
First NameLast NameEmailPhoneHours TodayHours This WeekHourly RateEstimated Weekly Earnings
Failed to fetch data.
{person.first_name}{person.last_name}{person.email}{person.phone}{person.hours_worked_today}{person.hours_worked_week}${person.hourly_rate.toFixed(2)}${person.estimated_weekly_earnings.toFixed(2)}
+
+
+ ); +}; + +export default WorkSchedule; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..f1e6f1b --- /dev/null +++ b/src/index.js @@ -0,0 +1,24 @@ +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { createRoot } from "react-dom/client"; +import Layout from "./Components/Layout"; +import Home from "./Pages/Home"; +import Login from "./Pages/Login"; +import Schedule from "./Pages/Scheduleinfo"; + +export default function App() { + return ( + + + }> + } /> + } /> + } /> + + + + ); +} + +const container = document.getElementById("app"); +const root = createRoot(container); // createRoot(container!) if you use TypeScript +root.render(); diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..9afe3f5 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,20 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'], + theme: { + extend: { + colors: { + 'nav-black': '#0b0f19', + 'background-black': '#101725', + 'darkGray': '#1A1A1A', + 'lightGray': '#B0B0B0', + 'highlightRed': '#FF3D5A', + }, + fontFamily: { + 'abril-fatface': ['Abril Fatface', 'display'], // Imported from https://fonts.bunny.net/css?family=abril-fatface:400|rubik:600,800i,900i + 'rubik': ['Rubik', 'sans-serif'], // Imported from https://fonts.bunny.net/css?family=abril-fatface:400|rubik:600,800i,900i + } + }, + }, + plugins: [], +}