diff --git a/api/controllers/serviceController.js b/api/controllers/serviceController.js
new file mode 100644
index 0000000..40472b0
--- /dev/null
+++ b/api/controllers/serviceController.js
@@ -0,0 +1,25 @@
+const Services = require("../models/serviceSchema");
+
+exports.findService = async (title) => {
+ try {
+ const serviceRes = await Services.find({ title });
+ return serviceRes;
+ } catch (err) {
+ throw err;
+ }
+};
+
+exports.createService = async ({ serviceType, title, desc, price }) => {
+ try {
+ const newService = new Service({
+ serviceType,
+ title,
+ desc,
+ price,
+ });
+ const service = await newService.save();
+ return service;
+ } catch (err) {
+ console.log(`error: ${err}`);
+ }
+};
diff --git a/api/models/serviceSchema.js b/api/models/serviceSchema.js
index 4598b63..e021a59 100644
--- a/api/models/serviceSchema.js
+++ b/api/models/serviceSchema.js
@@ -2,10 +2,28 @@ const mongoose = require("mongoose");
const { Schema } = mongoose;
//___ servicesSchema
-// service: String
+// serviceType: String
+// title: String
+// description: [String]
+// price: Number
const serviceSchema = new Schema({
- services: String,
+ serviceType: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ desc: {
+ type: [String],
+ required: true,
+ },
+ price: {
+ type: Number,
+ required: true,
+ },
});
-module.exports = serviceSchema;
+module.exports = mongoose.model("Services", serviceSchema);
diff --git a/api/routes/serviceRoutes.js b/api/routes/serviceRoutes.js
new file mode 100644
index 0000000..c08cf68
--- /dev/null
+++ b/api/routes/serviceRoutes.js
@@ -0,0 +1,52 @@
+const express = require("express");
+const router = express.Router();
+const Services = require("../models/serviceSchema");
+
+router.route("/").get(async (req, res) => {
+ try {
+ const services = await Services.find();
+ res.json(services);
+ } catch (err) {
+ res.json({ error: err });
+ }
+});
+
+router.route("/create").post(async (req, res) => {
+ const { serviceType, title, desc, price } = req.body;
+ if (!serviceType || serviceType === " ") {
+ res.status(400).json({ message: "service type must be provided" });
+ return;
+ }
+ if (!title || title === " ") {
+ res.status(400).json({ message: "title must be provided" });
+ return;
+ }
+ if (!desc || desc === " ") {
+ res.status(400).json({ message: "description must be provided" });
+ return;
+ }
+ if (!price || price === " ") {
+ res.status(400).json({ message: "price must be provided" });
+ return;
+ }
+ try {
+ const service = await findService(title);
+ if (service) {
+ res
+ .status(400)
+ .json({ message: `a service with this title already exists` });
+ }
+ const newService = await createService({
+ serviceType,
+ title,
+ desc,
+ price,
+ });
+ res.status(200).json({ data: { id: newService._id } });
+ } catch (err) {
+ console.log(err);
+ res.status(500).json({ message: "Internal server error" });
+ }
+});
+
+module.exports = router;
diff --git a/server.js b/server.js
index 363988c..31832d9 100644
--- a/server.js
+++ b/server.js
@@ -26,8 +26,10 @@ app.use(
// * EXPRESS ROUTER MINI-APP
const profile = require("./api/routes/profileRoutes");
const workorder = require("./api/routes/workorderRoutes");
+const services = require("./api/routes/serviceRoutes");
app.use("/api/profile", profile);
app.use("/api/workorder", workorder);
+app.use("/api/services", services);
if (process.env.NODE_ENV === "production") {
app.use(express.static("./build"));
@@ -55,4 +57,3 @@ mongoose
.catch((err) => {
console.log({ error: err });
});
-
diff --git a/src/App.css b/src/App.css
index 74b5e05..1a8c21d 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,4 +1,4 @@
-.App {
+/* .App {
text-align: center;
}
@@ -35,4 +35,4 @@
to {
transform: rotate(360deg);
}
-}
+} */
diff --git a/src/App.js b/src/App.js
index ff3c84f..9326670 100644
--- a/src/App.js
+++ b/src/App.js
@@ -5,30 +5,59 @@ import MainContentSection from "./components/root/MainContentSection";
import Footer from "./components/root/Footer";
import { ImpersonatorProvider } from "./backend/authorization/ImpersonatorContext";
import { UserProvider } from "./backend/authorization/UserContext";
-import { ThemeProvider } from "@material-ui/core";
-import theme from './styles/theme'
+import { makeStyles } from "@material-ui/core/styles";
+
+const useStyles = makeStyles((theme) => ({
+ header: {
+ display: "flex",
+ justifyContent: "space-between",
+ alignItems: "center",
+ height: "15vh",
+ // maxWidth: "900px",
+ padding: "2rem",
+ backgroundColor: "#212529",
+ },
+ main: {
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "center",
+ // width: "90%",
+ // maxWidth: "1200px",
+ margin: "0 auto",
+ height: "70vh",
+ backgroundColor: "gray",
+ },
+ footer: {
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "center",
+ alignItems: "center",
+ height: "15vh",
+ padding: "2rem",
+ backgroundColor: "#212529",
+ },
+}));
const App = () => {
+ const classes = useStyles();
const [loginClick, setLoginClick] = useState(false);
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/backend/authorization/AuthContainer.js b/src/backend/authorization/AuthContainer.js
index f669e19..ade1097 100644
--- a/src/backend/authorization/AuthContainer.js
+++ b/src/backend/authorization/AuthContainer.js
@@ -13,7 +13,7 @@ const useStyles = makeStyles((theme) => ({
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
- flexGrow: 1,
+ // flexGrow: 1,
"& > *": {
margin: theme.spacing(1),
},
@@ -41,6 +41,13 @@ const useStyles = makeStyles((theme) => ({
flexGrow: "50%",
flexBasis: "200px",
},
+ auth__button__container: {
+ display: "flex",
+ flexDirection: "column",
+ "& Button": {
+ marginBottom: "1rem",
+ },
+ },
}));
const AuthContainer = ({ loadUserProfile }) => {
@@ -123,19 +130,24 @@ const AuthContainer = ({ loadUserProfile }) => {
-
+
+
+
+
- {/* prettier-ignore */}
-
);
};
diff --git a/src/components/admin/Services.js b/src/components/admin/Services.js
new file mode 100644
index 0000000..f12e135
--- /dev/null
+++ b/src/components/admin/Services.js
@@ -0,0 +1,261 @@
+import React, { useEffect, useState, Fragment } from "react";
+import { makeStyles } from "@material-ui/core/styles";
+import TextField from "@material-ui/core/TextField";
+import Paper from "@material-ui/core/Paper";
+import Grid from "@material-ui/core/Grid";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ display: "flex",
+ flexWrap: "wrap",
+ justifyContent: "center",
+ flexGrow: 1,
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ textField: {
+ marginLEft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ width: "75%",
+ display: "flex",
+ justifyContent: "center",
+ },
+ paper: {
+ display: "flex",
+ width: "80%",
+ margin: "0 auto",
+ padding: "3rem 0",
+ rounded: false,
+ },
+ paperDispServices: {
+ display: "flex",
+ width: "30%",
+ margin: "0 auto",
+ padding: "3rem 0",
+ rounded: false,
+ },
+ paperText: {
+ rounded: false,
+ padding: 1,
+ },
+ grid__items: {
+ width: "100%",
+ },
+}));
+
+export default function Services() {
+ const classes = useStyles();
+ const [services, setServices] = useState({
+ type: null,
+ title: null,
+ desc: null,
+ price: null,
+ });
+
+ const loadServices = async function () {
+ try {
+ const response = await fetch("/api/services", {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ });
+
+ const json = await response.json();
+ if (!response.ok) {
+ throw new Error(json.message);
+ } else {
+ if (json.data) {
+ setServices(json.data);
+ } else {
+ console.log("no services are available");
+ }
+ }
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ useEffect(() => {
+ loadServices();
+ }, []);
+
+ const updateFields = (e) => {
+ const {
+ target: { name, value },
+ } = e;
+ if (name === "type") {
+ setServices({ ...services, type: value });
+ }
+ if (name === "title") {
+ setServices({ ...services, title: value });
+ }
+ if (name === "desc") {
+ setServices({ ...services, desc: value });
+ }
+ if (name === "price") {
+ setServices({ ...services, price: value });
+ } else;
+ };
+
+ const addRecord = async (e) => {
+ e.preventDefault();
+ const service = {
+ type: services.type,
+ title: services.title,
+ desc: services.desc,
+ price: services.price,
+ };
+ console.log(service);
+ try {
+ const response = await fetch("/api/services/create", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(service),
+ });
+ console.log(response);
+ const data = await response.json();
+ if (!response.ok) {
+ throw new Error(data.message);
+ }
+ setServices.type("");
+ setServices.title("");
+ setServices.desc("");
+ setServices.price("");
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ return (
+
+
+
+
+ {services.type ? (
+
+
+
+
+
+ {Object.values(services)}
+
+
+
+
+
+ ) : (
+ NO SERVICES
+ )}
+
+ );
+}
diff --git a/src/components/admin/ServicesInputForm.js b/src/components/admin/ServicesInputForm.js
new file mode 100644
index 0000000..aad8d8f
--- /dev/null
+++ b/src/components/admin/ServicesInputForm.js
@@ -0,0 +1,153 @@
+import React from "react";
+
+import { makeStyles } from "@material-ui/core/styles";
+import TextField from "@material-ui/core/TextField";
+import Paper from "@material-ui/core/Paper";
+import Grid from "@material-ui/core/Grid";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ display: "flex",
+ flexWrap: "wrap",
+ justifyContent: "center",
+ flexGrow: 1,
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ textField: {
+ marginLEft: theme.spacing(1),
+ marginRight: theme.spacing(1),
+ width: "75%",
+ display: "flex",
+ justifyContent: "center",
+ },
+ paper: {
+ display: "flex",
+ width: "80%",
+ margin: "0 auto",
+ padding: "3rem 0",
+ rounded: false,
+ },
+ paperText: {
+ rounded: false,
+ padding: 1,
+ },
+ grid__items: {
+ width: "100%",
+ },
+}));
+
+export default function ServicesInputForm(services, updateFields, addRecord) {
+ const classes = useStyles();
+ return (
+
+
+
+ );
+}
diff --git a/src/components/root/AdvertHero.js b/src/components/root/AdvertHero.js
index fd772d5..6b8d20f 100644
--- a/src/components/root/AdvertHero.js
+++ b/src/components/root/AdvertHero.js
@@ -1,13 +1,36 @@
-import React from 'react'
+import React from "react";
+import { makeStyles } from "@material-ui/core/styles";
+
+const useStyles = makeStyles(() => ({
+ advertHero__container: {
+ height: "100%",
+ width: "100vw",
+ padding: "3rem",
+ backgroundImage:
+ "url(https://triathlonmagazine.ca/wp-content/uploads/2020/04/VentumZ_105_ENVE_Editorial_H-scaled.jpg;)",
+ backgroundSize: "cover",
+ backgroundPosition: "bottom",
+ backgroundRepeat: "no-repeat",
+ overflow: "hidden",
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "flex-end",
+ alignItems: "flex-end",
+ },
+}));
function AdvertHero() {
+ const classes = useStyles();
return (
-
+
AERO
Work Order Management Tools
-
);
}
-export default AdvertHero
\ No newline at end of file
+export default AdvertHero;
diff --git a/src/components/root/Footer.js b/src/components/root/Footer.js
index be64744..ac3fa0a 100644
--- a/src/components/root/Footer.js
+++ b/src/components/root/Footer.js
@@ -1,14 +1,15 @@
import React from "react";
+import { Fragment } from "react";
function Footer() {
return (
-
+
thisdude.codes
mike@thisdude.codes
-
+
);
}
diff --git a/src/components/root/Header.js b/src/components/root/Header.js
index 4415c59..0e0397b 100644
--- a/src/components/root/Header.js
+++ b/src/components/root/Header.js
@@ -2,7 +2,7 @@ import React, { Fragment, useContext } from "react";
import { UserContext } from "../../backend/authorization/UserContext";
import { makeStyles } from "@material-ui/core/styles";
import Button from "@material-ui/core/Button";
-// import theme from '../../styles/theme'
+import { ImpersonatorContext } from "../../backend/authorization/ImpersonatorContext";
const useStyles = makeStyles((theme) => ({
root: {
@@ -10,11 +10,25 @@ const useStyles = makeStyles((theme) => ({
margin: theme.spacing(1),
},
},
+ Header: {
+ width: "100vw",
+ backgroundColor: "#212529",
+ },
+ header__container: {
+ display: "flex",
+ justifyContent: "space-between",
+ alignItems: "center",
+ margin: "0 auto",
+ height: "15vh",
+ maxWidth: "1200px",
+ padding: "2rem",
+ },
}));
function Header({ loginClick, setLoginClick }) {
const classes = useStyles();
const [currentUser, setCurrentUser] = useContext(UserContext);
+ const [admin, setAdmin] = useContext(ImpersonatorContext);
function toggleLoginClick() {
if (loginClick === false) {
@@ -26,43 +40,53 @@ function Header({ loginClick, setLoginClick }) {
function logout() {
setCurrentUser(undefined);
+ setAdmin(undefined);
toggleLoginClick();
}
let content;
- if (!currentUser) {
+ if (!currentUser && !admin) {
content = (
-
- AERO
- {loginClick ? (
-
- ) : (
+
+ );
+ } else {
+ content = (
+
);
}
diff --git a/src/components/root/Home.js b/src/components/root/Home.js
index a9c9533..905f693 100644
--- a/src/components/root/Home.js
+++ b/src/components/root/Home.js
@@ -1,11 +1,88 @@
-import React from "react";
+import React, { useContext } from "react";
+import { UserContext } from "../../backend/authorization/UserContext";
+import { ImpersonatorContext } from "../../backend/authorization/ImpersonatorContext";
+import { makeStyles } from "@material-ui/core/styles";
+import Paper from "@material-ui/core/Paper";
+import Grid from "@material-ui/core/Grid";
+import Card from "@material-ui/core/Card";
+import CardActions from "@material-ui/core/CardActions";
+import Button from "@material-ui/core/Button";
+import Typography from "@material-ui/core/Typography";
+import { CardActionArea, CardContent } from "@material-ui/core";
+
+const useStyles = makeStyles((theme) => ({
+ home__container: {
+ display: "flex",
+ },
+ paper: {
+ display: "flex",
+ width: "25%",
+ margin: "1rem auto",
+ padding: 1,
+ rounded: false,
+ },
+ paperText: {
+ rounded: false,
+ padding: 1,
+ },
+}));
function Home() {
- return (
-
-
Home Screen
+ const classes = useStyles();
+ const [admin] = useContext(ImpersonatorContext);
+ const [currentProfile] = useContext(UserContext);
+
+ let content;
+
+ // if (!admin && currentProfile) {
+ content = (
+
+ {/*
*/}
+
+
+ {/* */}
+
+ console.log("Basic")}>
+
+ Tune-up
+
+ BASIC
+
+
+ End-to-End checkup
+
+ Components cleaned and adjusted
+
+ Minor wheel true
+
+
+
+
+
+
+
+ console.log("Advanced")}>
+
+ Tune-up
+
+ ADVANCED
+
+
+ Basic plus:
+
+ All Bearings repacked
+
+ Components removed, inspected, and cleaned
+
+
+
+
+
+
);
+ // }
+ return content;
}
export default Home;
diff --git a/src/components/root/MainContentSection.js b/src/components/root/MainContentSection.js
index 5f415a6..983ee29 100644
--- a/src/components/root/MainContentSection.js
+++ b/src/components/root/MainContentSection.js
@@ -6,11 +6,52 @@ import Home from "./Home";
import SidebarNav from "./SidebarNav";
import Profile from "./Profile";
import Workorder from "./Workorder";
+import Services from "../admin/Services";
import Settings from "../admin/Settings";
import AdvertHero from "./AdvertHero";
import AuthContainer from "../../backend/authorization/AuthContainer";
+import { makeStyles } from "@material-ui/core/styles";
+
+const useStyles = makeStyles((theme) => ({
+ // root: {
+ // display: "flex",
+ // flexWrap: "wrap",
+ // justifyContent: "center",
+ // // flexGrow: 1,
+ // "& > *": {
+ // margin: theme.spacing(1),
+ // },
+ // backgroundColor: theme.palette.primary.dark,
+ // },
+ main__section__wrapper: {
+ height: "100%",
+ width: "100%",
+ maxWidth: "1200px",
+ margin: "0 auto",
+ display: "flex",
+ backgroundColor: "#5c677d",
+ },
+ sidebar__wrapper: {
+ width: "calc(100% / 4)",
+ height: "100%",
+ padding: "1rem",
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "space-between",
+ alignItems: "flex-start",
+ backgroundColor: "deepskyblue",
+ },
+ main__content: {
+ height: "100%",
+ width: "calc(100% / 4 * 3)",
+ display: "flex",
+ flexDirection: "column",
+ justifyContent: "space-between",
+ },
+}));
function MainContentSection({ loginClick }) {
+ const classes = useStyles();
const [admin, setAdmin] = useContext(ImpersonatorContext);
const [currentProfile, setCurrentProfile] = useContext(UserContext);
@@ -25,12 +66,13 @@ function MainContentSection({ loginClick }) {
const json = await response.json();
if (!response.ok) {
throw new Error(json.message);
- }
- if (json.data.admin === true) {
- setAdmin(json.data);
- setCurrentProfile(json.data);
} else {
- setCurrentProfile(json.data);
+ if (json.data.admin === true) {
+ setAdmin(json.data);
+ setCurrentProfile(json.data);
+ } else {
+ setCurrentProfile(json.data);
+ }
}
} catch (err) {
console.log(err);
@@ -44,42 +86,39 @@ function MainContentSection({ loginClick }) {
if (loginClick) {
if (admin) {
content = (
-
-
+
);
} else if (!admin && currentProfile) {
content = (
-
-
+
);
} else {
content =
;
@@ -88,7 +127,7 @@ function MainContentSection({ loginClick }) {
content = (
- ;
+
);
}
diff --git a/src/components/root/Profile.js b/src/components/root/Profile.js
index 48a85f1..ec837a6 100644
--- a/src/components/root/Profile.js
+++ b/src/components/root/Profile.js
@@ -2,27 +2,18 @@ import React from "react";
import ProfileDisplay from "./ProfileDisplay";
import ProfileSearch from "./ProfilesSearch";
-// _______ Profile
-// Return two buttons that control whether to Sign In or Sign Up or add
-// On Login check if currentProfile exists in DB
-// IF user is ADMIN show everything
-
-const Profile = ({
- admin,
- currentProfile,
- setCurrentProfile,
-}) => {
+const Profile = ({ admin, currentProfile, setCurrentProfile }) => {
let content;
if (admin) {
// if (!currentProfile._id) {
- content = (
-
- );
+ content = (
+ //
+ );
// } else {
// content =
;
// // and show some additional settings, like change currentProfile
diff --git a/src/components/root/ProfileCreate.js b/src/components/root/ProfileCreate.js
index 421d812..a0137d6 100644
--- a/src/components/root/ProfileCreate.js
+++ b/src/components/root/ProfileCreate.js
@@ -15,6 +15,8 @@ const useStyles = makeStyles((theme) => ({
"& > *": {
margin: theme.spacing(1),
},
+ flexDirection: "column",
+ alignItems: "center",
},
textField: {
marginLEft: theme.spacing(1),
@@ -25,15 +27,18 @@ const useStyles = makeStyles((theme) => ({
},
paper: {
display: "flex",
- width: "75%",
+ width: "80%",
margin: "0 auto",
- padding: 1,
+ padding: "3rem 0",
rounded: false,
},
paperText: {
rounded: false,
padding: 1,
},
+ grid__items: {
+ width: "100%",
+ },
}));
function ProfileCreate({ changeLink }) {
@@ -167,7 +172,7 @@ function ProfileCreate({ changeLink }) {