continuing to build on ui, starting on add recipe

This commit is contained in:
Mikayla Dobson
2022-12-05 18:16:15 -06:00
parent 6b1312018f
commit d8aae8593c
14 changed files with 228 additions and 26 deletions

View File

@@ -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>

View File

@@ -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;

View File

@@ -0,0 +1,11 @@
import { Page } from "../ui";
const CollectionBrowser = () => {
return (
<Page>
<h1>Browsing your {2} collections:</h1>
</Page>
)
}
export default CollectionBrowser;

View File

@@ -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 />

View File

@@ -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;

View File

@@ -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>

View File

@@ -0,0 +1,5 @@
const CustomPicker = () => {
}
export default CustomPicker;

View 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;

View File

@@ -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>
)
}

View File

@@ -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;

View File

@@ -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
}

View 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;
}
}
}
}

View File

@@ -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
}

View File

@@ -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 {