Skip to content
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# React-Firebase-1

My react firebase app

*it didn't work the first time so I had to fork and keep pushing/commiting
21,494 changes: 21,476 additions & 18 deletions cooking-ninja/package-lock.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions cooking-ninja/src/App.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.App {
min-height: 100%;
}

.App.dark {
background: #333;
}
8 changes: 7 additions & 1 deletion cooking-ninja/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,21 @@ import Home from './pages/home/Home'
import Create from './pages/create/Create'
import Search from './pages/search/Search'
import Recipe from './pages/recipe/Recipe'
import ThemeSelector from './components/ThemeSelector'


// styles
import './App.css'
import { useTheme } from './hooks/useTheme'

function App() {
const {mode} = useTheme()

return (
<div className="App">
<div className={`App ${mode}`}>
<BrowserRouter>
<Navbar />
<ThemeSelector />
<Switch>
<Route exact path="/">
<Home />
Expand Down
1 change: 1 addition & 0 deletions cooking-ninja/src/assets/mode-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion cooking-ninja/src/components/Navbar.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { Link } from 'react-router-dom'
// import { useContext } from 'react'
// import { ThemeContext } from '../context/ThemeContext'
import {useTheme} from '../hooks/useTheme'

// styles
import './Navbar.css'
import Searchbar from './Searchbar'

export default function Navbar() {


const {color} = useTheme()
return (
<div className="navbar">
<div className="navbar" style={{background: color}}>
<nav>
<Link to="/" className="brand">
<h1>Cooking Ninja</h1>
Expand Down
10 changes: 10 additions & 0 deletions cooking-ninja/src/components/RecipeList.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,14 @@
padding: 8px;
border-radius: 4px;
margin: 20px auto 0;
}

/* dark mode */
.recipe-list .card.dark {
background: #555;
}
.recipe-list .card.dark p,
.recipe-list .card.dark h3,
.recipe-list .card.dark div {
color: #e4e4e4;
}
4 changes: 3 additions & 1 deletion cooking-ninja/src/components/RecipeList.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Link } from 'react-router-dom'
import {useTheme} from '../hooks/useTheme'

// styles
import './RecipeList.css'

export default function RecipeList({ recipes }) {
const {mode} = useTheme()

if (recipes.length === 0) {
return <div className="error">No recipes to load...</div>
Expand All @@ -12,7 +14,7 @@ export default function RecipeList({ recipes }) {
return (
<div className="recipe-list">
{recipes.map(recipe => (
<div key={recipe.id} className="card">
<div key={recipe.id} className={`card ${mode}`}>
<h3>{recipe.title}</h3>
<p>{recipe.cookingTime} to make.</p>
<div>{recipe.method.substring(0, 100)}...</div>
Expand Down
26 changes: 26 additions & 0 deletions cooking-ninja/src/components/ThemeSelector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.theme-selector {
display: flex;
justify-content: flex-end;
align-items: center;
max-width: 1200px;
margin: 20px auto;
}

.theme-buttons div {
display: inline-block;
width: 20px;
height: 20px;
cursor: pointer;
margin-left: 15px;
border-radius: 50%;
}

.mode-toggle {
margin-right: auto;
}

.mode-toggle img {
width: 24px;
height: 24px;
cursor: pointer;
}
40 changes: 40 additions & 0 deletions cooking-ninja/src/components/ThemeSelector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import {useTheme} from "../hooks/useTheme"
import modeIcon from '../assets/mode-icon.svg'

// styles
import './ThemeSelector.css'

const themeColors = ['#58249c', '#249c6b', '#b70233', '#fec0c5']

export default function ThemeSelector() {

const {changeColor, changeMode, mode} = useTheme()

const toggleMode = () => {
changeMode(mode === 'light' ? 'dark' : 'light')
}
console.log(mode)

return (
<div className="theme-selector">
<div className="mode-toggle">
<img
onClick={toggleMode}
src={modeIcon}
alt="mode icon"
style={{filter: mode === 'dark' ? 'invert(100%)' : 'invert(20%)'}}
/>
</div>
<div className="theme-buttons">
{themeColors.map(color => (
<div
key={color}
onClick={() => changeColor(color)}
style={{background: color}}
/>
))}
</div>

</div>
)
}
35 changes: 35 additions & 0 deletions cooking-ninja/src/context/ThemeContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {createContext, useReducer} from 'react'

export const ThemeContext = createContext()

const themeReducer = (state, action) => {
switch (action.type) {
case 'CHANGE_COLOR':
return {...state, color: action.payload}
case 'CHANGE_MODE':
return { ...state, mode: action.payload}
}
}

export function ThemeProvider({children}) {

const [state, dispatch] = useReducer(themeReducer, {
color: '#58249c',
mode: 'light'
})

const changeColor = (color) => {
dispatch({type: 'CHANGE_COLOR', payload: color})
}
const changeMode = (mode) => {
dispatch({type: 'CHANGE_MODE', payload: mode})
}

// custon logic

return (
<ThemeContext.Provider value={{...state, changeColor, changeMode}}>
{children}
</ThemeContext.Provider>
)
}
Empty file.
13 changes: 13 additions & 0 deletions cooking-ninja/src/hooks/useTheme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {useContext} from 'react'
import {ThemeContext} from '../context/ThemeContext'


export const useTheme = () => {
const context = useContext(ThemeContext)

if (context === undefined) {
throw new Error("useTheme() must be used inside a theme provider")
}

return context
}
3 changes: 3 additions & 0 deletions cooking-ninja/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { ThemeProvider } from './context/ThemeContext';

ReactDOM.render(
<React.StrictMode>
<ThemeProvider>
<App />
</ThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
6 changes: 6 additions & 0 deletions cooking-ninja/src/pages/recipe/Recipe.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,10 @@
.method {
text-align: left;
line-height: 1.5em;
}

/* dark mode */
.recipe.dark {
background: #555;
color: #e4e4e4;
}
4 changes: 3 additions & 1 deletion cooking-ninja/src/pages/recipe/Recipe.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useParams } from 'react-router-dom'
import { useFetch } from '../../hooks/useFetch'
import {useTheme} from '../../hooks/useTheme'

// styles
import './Recipe.css'
Expand All @@ -8,9 +9,10 @@ export default function Recipe() {
const { id } = useParams()
const url = 'http://localhost:3000/recipes/' + id
const { error, isPending, data: recipe } = useFetch(url)
const {mode} = useTheme()

return (
<div className="recipe">
<div className={`recipe ${mode}`}>
{error && <p className="error">{error}</p>}
{isPending && <p className="loading">Loading...</p>}
{recipe && (
Expand Down