forked from adrianostankewicz/fc3-codeflix
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 77cccf0
Showing
27 changed files
with
1,429 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Redux Toolkit TypeScript Example | ||
|
||
This example shows how to integrate Next.js with [Redux Toolkit](https://redux-toolkit.js.org). | ||
|
||
**Redux Toolkit**(also known as "RTK" for short) provides a standardized way to write Redux logic. It includes utilities that help simplify many common use cases, including [store setup](https://redux-toolkit.js.org/api/configureStore), [creating reducers and writing immutable update logic](https://redux-toolkit.js.org/api/createreducer), and even [creating entire "slices" of state at once](https://redux-toolkit.js.org/api/createslice). This example showcases each of these features in conjunction with Next.js. | ||
|
||
## Deploy Your Own | ||
|
||
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example): | ||
|
||
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-redux&project-name=with-redux&repository-name=with-redux) | ||
|
||
## How to Use | ||
|
||
Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example: | ||
|
||
```bash | ||
npx create-next-app --example with-redux with-redux-app | ||
``` | ||
|
||
```bash | ||
yarn create next-app --example with-redux with-redux-app | ||
``` | ||
|
||
```bash | ||
pnpm create next-app --example with-redux with-redux-app | ||
``` | ||
|
||
Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
"use client"; | ||
import type { AppStore } from "@/lib/store"; | ||
import { makeStore } from "@/lib/store"; | ||
import { setupListeners } from "@reduxjs/toolkit/query"; | ||
import type { ReactNode } from "react"; | ||
import { useEffect, useRef } from "react"; | ||
import { Provider } from "react-redux"; | ||
|
||
interface Props { | ||
readonly children: ReactNode; | ||
} | ||
|
||
export const StoreProvider = ({ children }: Props) => { | ||
const storeRef = useRef<AppStore | null>(null); | ||
|
||
if (!storeRef.current) { | ||
// Create the store instance the first time this renders | ||
storeRef.current = makeStore(); | ||
} | ||
|
||
useEffect(() => { | ||
if (storeRef.current != null) { | ||
// configure listeners using the provided defaults | ||
// optional, but required for `refetchOnFocus`/`refetchOnReconnect` behaviors | ||
const unsubscribe = setupListeners(storeRef.current.dispatch); | ||
return unsubscribe; | ||
} | ||
}, []); | ||
|
||
return <Provider store={storeRef.current}>{children}</Provider>; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import type { NextRequest } from "next/server"; | ||
import { NextResponse } from "next/server"; | ||
|
||
interface Context { | ||
params: undefined; | ||
} | ||
|
||
export async function POST(request: NextRequest, context: Context) { | ||
const body: { amount: number } = await request.json(); | ||
const { amount = 1 } = body; | ||
|
||
// simulate IO latency | ||
await new Promise((resolve) => setTimeout(resolve, 500)); | ||
|
||
return NextResponse.json({ data: amount }); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
"use client"; | ||
|
||
import Link from "next/link"; | ||
import { usePathname } from "next/navigation"; | ||
|
||
import styles from "../styles/layout.module.css"; | ||
|
||
export const Nav = () => { | ||
const pathname = usePathname(); | ||
|
||
return ( | ||
<nav className={styles.nav}> | ||
<Link | ||
className={`${styles.link} ${pathname === "/" ? styles.active : ""}`} | ||
href="/" | ||
> | ||
Home | ||
</Link> | ||
<Link | ||
className={`${styles.link} ${ | ||
pathname === "/verify" ? styles.active : "" | ||
}`} | ||
href="/verify" | ||
> | ||
Verify | ||
</Link> | ||
<Link | ||
className={`${styles.link} ${ | ||
pathname === "/quotes" ? styles.active : "" | ||
}`} | ||
href="/quotes" | ||
> | ||
Quotes | ||
</Link> | ||
</nav> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
.row { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
|
||
.row > button { | ||
margin-left: 4px; | ||
margin-right: 8px; | ||
} | ||
|
||
.row:not(:last-child) { | ||
margin-bottom: 16px; | ||
} | ||
|
||
.value { | ||
font-size: 78px; | ||
padding-left: 16px; | ||
padding-right: 16px; | ||
margin-top: 2px; | ||
font-family: "Courier New", Courier, monospace; | ||
} | ||
|
||
.button { | ||
appearance: none; | ||
background: none; | ||
font-size: 32px; | ||
padding-left: 12px; | ||
padding-right: 12px; | ||
outline: none; | ||
border: 2px solid transparent; | ||
color: rgb(112, 76, 182); | ||
padding-bottom: 4px; | ||
cursor: pointer; | ||
background-color: rgba(112, 76, 182, 0.1); | ||
border-radius: 2px; | ||
transition: all 0.15s; | ||
} | ||
|
||
.textbox { | ||
font-size: 32px; | ||
padding: 2px; | ||
width: 64px; | ||
text-align: center; | ||
margin-right: 4px; | ||
} | ||
|
||
.button:hover, | ||
.button:focus { | ||
border: 2px solid rgba(112, 76, 182, 0.4); | ||
} | ||
|
||
.button:active { | ||
background-color: rgba(112, 76, 182, 0.2); | ||
} | ||
|
||
.asyncButton { | ||
composes: button; | ||
position: relative; | ||
} | ||
|
||
.asyncButton:after { | ||
content: ""; | ||
background-color: rgba(112, 76, 182, 0.15); | ||
display: block; | ||
position: absolute; | ||
width: 100%; | ||
height: 100%; | ||
left: 0; | ||
top: 0; | ||
opacity: 0; | ||
transition: | ||
width 1s linear, | ||
opacity 0.5s ease 1s; | ||
} | ||
|
||
.asyncButton:active:after { | ||
width: 0%; | ||
opacity: 1; | ||
transition: 0s; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
"use client"; | ||
|
||
import { useState } from "react"; | ||
|
||
import { | ||
decrement, | ||
increment, | ||
incrementAsync, | ||
incrementByAmount, | ||
incrementIfOdd, | ||
selectCount, | ||
selectStatus, | ||
} from "@/lib/features/counter/counterSlice"; | ||
|
||
import { useAppDispatch, useAppSelector } from "@/lib/hooks"; | ||
import styles from "./Counter.module.css"; | ||
|
||
export const Counter = () => { | ||
const dispatch = useAppDispatch(); | ||
const count = useAppSelector(selectCount); | ||
const status = useAppSelector(selectStatus); | ||
const [incrementAmount, setIncrementAmount] = useState("2"); | ||
|
||
const incrementValue = Number(incrementAmount) || 0; | ||
|
||
return ( | ||
<div> | ||
<div className={styles.row}> | ||
<button | ||
className={styles.button} | ||
aria-label="Decrement value" | ||
onClick={() => dispatch(decrement())} | ||
> | ||
- | ||
</button> | ||
<span aria-label="Count" className={styles.value}> | ||
{count} | ||
</span> | ||
<button | ||
className={styles.button} | ||
aria-label="Increment value" | ||
onClick={() => dispatch(increment())} | ||
> | ||
+ | ||
</button> | ||
</div> | ||
<div className={styles.row}> | ||
<input | ||
className={styles.textbox} | ||
aria-label="Set increment amount" | ||
value={incrementAmount} | ||
type="number" | ||
onChange={(e) => { | ||
setIncrementAmount(e.target.value); | ||
}} | ||
/> | ||
<button | ||
className={styles.button} | ||
onClick={() => dispatch(incrementByAmount(incrementValue))} | ||
> | ||
Add Amount | ||
</button> | ||
<button | ||
className={styles.asyncButton} | ||
disabled={status !== "idle"} | ||
onClick={() => dispatch(incrementAsync(incrementValue))} | ||
> | ||
Add Async | ||
</button> | ||
<button | ||
className={styles.button} | ||
onClick={() => { | ||
dispatch(incrementIfOdd(incrementValue)); | ||
}} | ||
> | ||
Add If Odd | ||
</button> | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
.select { | ||
font-size: 25px; | ||
padding: 5px; | ||
padding-top: 2px; | ||
padding-bottom: 2px; | ||
size: 50; | ||
outline: none; | ||
border: 2px solid transparent; | ||
color: rgb(112, 76, 182); | ||
cursor: pointer; | ||
background-color: rgba(112, 76, 182, 0.1); | ||
border-radius: 5px; | ||
transition: all 0.15s; | ||
} | ||
|
||
.container { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"use client"; | ||
import { useGetQuotesQuery } from "@/lib/features/quotes/quotesApiSlice"; | ||
import { useState } from "react"; | ||
import styles from "./Quotes.module.css"; | ||
|
||
const options = [5, 10, 20, 30]; | ||
|
||
export const Quotes = () => { | ||
const [numberOfQuotes, setNumberOfQuotes] = useState(10); | ||
// Using a query hook automatically fetches data and returns query values | ||
const { data, isError, isLoading, isSuccess } = | ||
useGetQuotesQuery(numberOfQuotes); | ||
|
||
if (isError) { | ||
return ( | ||
<div> | ||
<h1>There was an error!!!</h1> | ||
</div> | ||
); | ||
} | ||
|
||
if (isLoading) { | ||
return ( | ||
<div> | ||
<h1>Loading...</h1> | ||
</div> | ||
); | ||
} | ||
|
||
if (isSuccess) { | ||
return ( | ||
<div className={styles.container}> | ||
<h3>Select the Quantity of Quotes to Fetch:</h3> | ||
<select | ||
className={styles.select} | ||
value={numberOfQuotes} | ||
onChange={(e) => { | ||
setNumberOfQuotes(Number(e.target.value)); | ||
}} | ||
> | ||
{options.map((option) => ( | ||
<option key={option} value={option}> | ||
{option} | ||
</option> | ||
))} | ||
</select> | ||
{data.quotes.map(({ author, quote, id }) => ( | ||
<blockquote key={id}> | ||
“{quote}” | ||
<footer> | ||
<cite>{author}</cite> | ||
</footer> | ||
</blockquote> | ||
))} | ||
</div> | ||
); | ||
} | ||
|
||
return null; | ||
}; |
Binary file not shown.
Oops, something went wrong.