continuing to build on ui, starting on add recipe
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||
// framework tools and custom utils
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||
import { AuthContext, IAuthContext, useAuthContext } from './context/AuthContext';
|
||||
import { attemptLogout, checkCredientials } from './util/apiUtils';
|
||||
import { IUser } from './schemas';
|
||||
import { checkCredientials } from './util/apiUtils';
|
||||
|
||||
// pages, ui, styles
|
||||
import Subscriptions from './components/pages/Subscriptions/Subscriptions';
|
||||
import Browser from './components/pages/Browser';
|
||||
import Collection from './components/pages/Collection';
|
||||
@@ -11,8 +14,10 @@ import Profile from './components/pages/Profile';
|
||||
import Recipe from './components/pages/Recipe';
|
||||
import Register from './components/pages/Register';
|
||||
import Welcome from './components/pages/Welcome';
|
||||
import './sass/App.scss'
|
||||
import AddRecipe from './components/pages/AddRecipe';
|
||||
import CollectionBrowser from './components/pages/CollectionBrowser';
|
||||
import { Navbar } from './components/ui';
|
||||
import './sass/App.scss'
|
||||
|
||||
function App() {
|
||||
const [user, setUser] = useState<IAuthContext>({ user: undefined });
|
||||
@@ -51,11 +56,14 @@ function App() {
|
||||
<Route path="/register" element={<Register receiveChange={receiveChange} />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
<Route path="/collection" element={<Collection />} />
|
||||
<Route path="/collections" element={<CollectionBrowser />} />
|
||||
<Route path="/collections/:id" element={<Collection />} />
|
||||
<Route path="/explore" element={<Browser />} />
|
||||
<Route path="/recipe/:id" element={<Recipe />} />
|
||||
<Route path="/subscriptions" element={<Subscriptions />} />
|
||||
<Route path="/subscriptions/:id" element={<Collection />} />
|
||||
|
||||
<Route path="/add-recipe" element={<AddRecipe />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</AuthContext.Provider>
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useAuthContext } from "../../context/AuthContext";
|
||||
import { IRecipe } from "../../schemas";
|
||||
import { Button, Divider, Form, Page, Panel } from "../ui"
|
||||
|
||||
const AddRecipe = () => {
|
||||
const { user } = useAuthContext();
|
||||
const [input, setInput] = useState<IRecipe>({ name: '', preptime: '', description: '', authoruserid: user?.id || '', ingredients: [] })
|
||||
const [form, setForm] = useState<JSX.Element[]>();
|
||||
|
||||
const getFormState = useCallback((data: IRecipe) => {
|
||||
setInput(data);
|
||||
}, [])
|
||||
|
||||
const handleCreate = () => {
|
||||
for (let field of Object.keys(input)) {
|
||||
if (!input[field as keyof IRecipe]) return;
|
||||
}
|
||||
|
||||
console.log('good to go!')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
setInput((prev: IRecipe) => {
|
||||
return {
|
||||
...prev,
|
||||
authoruserid: user.id!
|
||||
}
|
||||
})
|
||||
}
|
||||
}, [user])
|
||||
|
||||
useEffect(() => {
|
||||
setForm(
|
||||
new Form<IRecipe>({
|
||||
parent: "AddRecipe",
|
||||
keys: ["name", "preptime", "ingredients", "description"],
|
||||
labels: ["Recipe Name:", "Prep Time:", "Ingredients:", "Description:"],
|
||||
dataTypes: ['text', 'text', 'custom picker', 'text'],
|
||||
initialState: input,
|
||||
getState: getFormState
|
||||
}).mount()
|
||||
)
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<h1>Add a New Recipe</h1>
|
||||
<Divider />
|
||||
|
||||
<Panel>
|
||||
{ form }
|
||||
<Button onClick={handleCreate}>Create Recipe!</Button>
|
||||
</Panel>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
export default AddRecipe;
|
||||
11
client/src/components/pages/CollectionBrowser.tsx
Normal file
11
client/src/components/pages/CollectionBrowser.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Page } from "../ui";
|
||||
|
||||
const CollectionBrowser = () => {
|
||||
return (
|
||||
<Page>
|
||||
<h1>Browsing your {2} collections:</h1>
|
||||
</Page>
|
||||
)
|
||||
}
|
||||
|
||||
export default CollectionBrowser;
|
||||
@@ -21,21 +21,14 @@ const Welcome = () => {
|
||||
<Panel extraStyles="inherit-background c-papyrus uppercase">
|
||||
<h2>Ready to get started?</h2>
|
||||
<Button onClick={() => navigate('/register')}>Register</Button>
|
||||
<Button onClick={attemptLogout}>Log Out</Button>
|
||||
</Panel>
|
||||
)
|
||||
|
||||
const unwrap = async () => {
|
||||
const result = await checkCredientials();
|
||||
console.log(result);
|
||||
}
|
||||
|
||||
return (
|
||||
<Page extraStyles="narrow-dividers">
|
||||
<Panel extraStyles='inherit-background c-papyrus uppercase'>
|
||||
<h1>Welcome to Recipin</h1>
|
||||
<Button onClick={unwrap}>Check Credentials</Button>
|
||||
<Button onClick={() => console.log(authContext)}>Auth Context</Button>
|
||||
<Button onClick={attemptLogout}>Log Out</Button>
|
||||
</Panel>
|
||||
|
||||
<Divider />
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import { FC } from "react";
|
||||
import { Panel } from ".";
|
||||
import { PortalBase } from "../../util/types";
|
||||
import "/src/sass/components/Dropdown.scss";
|
||||
|
||||
// expects to receive buttons as children
|
||||
const Dropdown: FC<PortalBase> = ({ children, extraStyles = null }) => {
|
||||
return (
|
||||
<Panel extraStyles={`ui-dropdown ${extraStyles}`}>
|
||||
{ children }
|
||||
</Panel>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dropdown;
|
||||
@@ -54,6 +54,11 @@ export default class Form<T>{
|
||||
let output = new Array<JSX.Element>();
|
||||
|
||||
for (let i = 0; i < this.keys.length; i++) {
|
||||
if (this.dataTypes[i] == 'custom picker') {
|
||||
console.log('noted!');
|
||||
this.dataTypes[i] = 'text';
|
||||
}
|
||||
|
||||
output.push(
|
||||
<div id={`${this.parent}-row-${i}`} key={v4()}>
|
||||
<label htmlFor={`${this.parent}-${this.keys[i]}`}>{this.labels[i]}</label>
|
||||
|
||||
5
client/src/components/ui/FormElements/CustomPicker.tsx
Normal file
5
client/src/components/ui/FormElements/CustomPicker.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
const CustomPicker = () => {
|
||||
|
||||
}
|
||||
|
||||
export default CustomPicker;
|
||||
20
client/src/components/ui/FormElements/OptionFetcher.tsx
Normal file
20
client/src/components/ui/FormElements/OptionFetcher.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { FC } from "react";
|
||||
import { PortalBase } from "../../../util/types";
|
||||
|
||||
interface FetcherParams extends PortalBase {
|
||||
fetchTarget: string
|
||||
}
|
||||
|
||||
const OptionFetcher: FC<FetcherParams> = ({ children, fetchTarget }) => {
|
||||
const fetchOptions = async () => {
|
||||
console.log(fetchTarget);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ children }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default OptionFetcher;
|
||||
@@ -1,25 +1,65 @@
|
||||
import { attemptLogout } from "../../../util/apiUtils";
|
||||
import { NavbarType } from "../../../util/types";
|
||||
import Button from "../Button";
|
||||
import { Button, Dropdown } from '../.'
|
||||
import { useState } from "react";
|
||||
|
||||
const LoggedIn: NavbarType = ({ received, liftChange, navigate }) => {
|
||||
const [dropdownActive, setDropdownActive] = useState(false);
|
||||
const [searchActive, setSearchActive] = useState(false);
|
||||
|
||||
const handleLogout = async () => {
|
||||
const success = await attemptLogout();
|
||||
if (success) liftChange!(undefined);
|
||||
navigate('/');
|
||||
}
|
||||
|
||||
const handleUIChange = (target: string) => {
|
||||
if (target == "SEARCH") {
|
||||
setSearchActive(!searchActive);
|
||||
setDropdownActive(false);
|
||||
} else {
|
||||
setSearchActive(false);
|
||||
setDropdownActive(!dropdownActive);
|
||||
}
|
||||
}
|
||||
|
||||
const handleOptionSelect = (payload: string) => {
|
||||
setSearchActive(false);
|
||||
setDropdownActive(false);
|
||||
navigate(payload);
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
<span id="search-icon"></span>
|
||||
<Button onClick={() => navigate('/profile')}>Profile</Button>
|
||||
<Button onClick={handleLogout}>Log Out</Button>
|
||||
<div>
|
||||
<div id="navbar">
|
||||
<div className="navbar-block">
|
||||
<a onClick={() => navigate('/')}>RECIPIN</a>
|
||||
</div>
|
||||
<div className="navbar-block">
|
||||
<p>Hi, {received?.firstname}.</p>
|
||||
<span id="search-icon"></span>
|
||||
<Button onClick={() => handleUIChange("SEARCH")}>Search</Button>
|
||||
<Button onClick={() => handleUIChange("ACTIONS")}>Actions</Button>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
dropdownActive && (
|
||||
<Dropdown extraStyles="top-menu-bar actions-bar">
|
||||
<Button onClick={() => handleOptionSelect('/add-recipe')}>Add a Recipe</Button>
|
||||
<Button onClick={() => handleOptionSelect('/collections')}>My Collections</Button>
|
||||
<Button onClick={() => handleOptionSelect('/subscriptions')}>Subscriptions</Button>
|
||||
<Button onClick={() => handleOptionSelect('/profile')}>Profile</Button>
|
||||
<Button onClick={handleLogout}>Log Out</Button>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
{
|
||||
searchActive && (
|
||||
<Dropdown extraStyles="top-menu-bar search-bar">
|
||||
<Button>Run Search</Button>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { FC } from "react";
|
||||
import { PortalBase } from "../../util/types";
|
||||
|
||||
const Tooltip: FC<PortalBase> = ({ children, extraStyles = null }) => {
|
||||
return (
|
||||
<aside className={`ui-tooltip ${extraStyles}`}>
|
||||
{ children }
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tooltip;
|
||||
@@ -1,13 +1,15 @@
|
||||
import Button from "./Button";
|
||||
import Card from "./Card";
|
||||
import Divider from "./Divider";
|
||||
import Dropdown from "./Dropdown";
|
||||
import Form from "./Form";
|
||||
import Navbar from "./Navbar";
|
||||
import Page from "./Page";
|
||||
import Panel from "./Panel";
|
||||
import UserCard from "./UserCard";
|
||||
import TextField from "./TextField";
|
||||
import Tooltip from "./Tooltip";
|
||||
import UserCard from "./UserCard";
|
||||
|
||||
export {
|
||||
Button, Card, Divider, Form, Navbar, Page, Panel, UserCard, TextField
|
||||
Button, Card, Dropdown, Divider, Form, Navbar, Page, Panel, TextField, Tooltip, UserCard
|
||||
}
|
||||
29
client/src/sass/components/Dropdown.scss
Normal file
29
client/src/sass/components/Dropdown.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
.ui-dropdown {
|
||||
&.top-menu-bar {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
top: 5rem;
|
||||
background-color: rgb(52, 29, 29);
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
z-index: 3;
|
||||
width: 100%;
|
||||
|
||||
.ui-button {
|
||||
background-color: red;
|
||||
margin: 0 1rem;
|
||||
z-index: 7;
|
||||
|
||||
&:hover {
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { Form } from "../components/ui";
|
||||
import { IUser } from "../schemas";
|
||||
|
||||
interface PortalBase {
|
||||
export interface PortalBase {
|
||||
children?: ReactNode
|
||||
extraStyles?: string
|
||||
}
|
||||
|
||||
@@ -29,9 +29,10 @@ export interface IUserAuth {
|
||||
|
||||
export interface IRecipe extends HasHistory, CanDeactivate {
|
||||
name: string
|
||||
description?: string
|
||||
preptime: string
|
||||
authoruserid: string | number
|
||||
description?: string
|
||||
ingredients?: string[]
|
||||
}
|
||||
|
||||
export interface IIngredient extends HasHistory {
|
||||
|
||||
Reference in New Issue
Block a user