Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add example/nextjs-app-router #334

Merged
merged 9 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 7 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 .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npm test
./node_modules/.bin/lint-staged
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "nextjs-root-layout",
"name": "nextjs-app-router",
"version": "0.1.0",
"private": true,
"scripts": {
Expand All @@ -9,15 +9,16 @@
"lint": "next lint"
},
"dependencies": {
"@stripe/stripe-js": "^1.14.0",
"autoprefixer": "10.4.14",
"eslint": "8.40.0",
"eslint-config-next": "13.4.1",
"next": "13.4.1",
"postcss": "8.4.23",
"react": "18.2.0",
"react-dom": "18.2.0",
"stripe": "^13.10.0",
"tailwindcss": "3.3.2",
"use-shopping-cart": "workspace:^3.1.5"
"use-shopping-cart": "3.2.0-alpha.0"
}
}

61 changes: 61 additions & 0 deletions examples/nextjs-app-router/src/app/components/CheckoutButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { useState } from 'react'
import { useShoppingCart } from 'use-shopping-cart'

export default function CheckoutButton() {
const [status, setStatus] = useState('idle')
const { redirectToCheckout, cartCount, totalPrice, cartDetails } =
useShoppingCart()

async function handleClick(event) {
event.preventDefault()
if (cartCount > 0) {
setStatus('loading')
try {
const res = await fetch('/session', {
method: 'POST',
body: JSON.stringify(cartDetails)
})
const data = await res.json()
const result = await redirectToCheckout(data.sessionId)
if (result?.error) {
console.error(result)
setStatus('redirect-error')
}
} catch (error) {
console.error(error)
setStatus('redirect-error')
}
} else {
setStatus('no-items')
}
}

return (
<article className="mt-3 flex flex-col">
<div className="text-red-700 text-xs mb-3 h-5 text-center">
{totalPrice && totalPrice < 30
? 'You must have at least £0.30 in your basket'
: cartCount && cartCount > 20
? 'You cannot have more than 20 items'
: status === 'redirect-error'
? 'Unable to redirect to Stripe checkout page'
: status === 'no-items'
? 'Please add some items to your cart'
: null}
</div>
<button
onClick={handleClick}
className="bg-emerald-50 hover:bg-emerald-500 hover:text-white transition-colors duration-500 text-emerald-500 py-3 px-5 rounded-md w-100 disabled:bg-slate-300 disabled:cursor-not-allowed disabled:text-white"
disabled={
(totalPrice && totalPrice < 30) ||
(cartCount && cartCount > 20) ||
status == 'no-items'
? true
: false
}
>
{status !== 'loading' ? 'Proceed to checkout' : 'Loading...'}
</button>
</article>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ShoppingCart from './ShoppingCart'
export default function NavBar() {
const { handleCartClick, cartCount } = useShoppingCart()
return (
<nav className="py-5 px-12 flex justify-between">
<nav className="py-5 bg-white px-12 flex justify-between">
<Link href="/">
<p className="bg-white text-3xl font-bold underline underline-offset-4 decoration-wavy decoration-2 decoration-emerald-500">
fresh
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use client'

import { useState } from 'react'
import { formatCurrencyString } from 'use-shopping-cart'
import { useShoppingCart } from 'use-shopping-cart'
import { formatCurrencyString, useShoppingCart } from 'use-shopping-cart'

export default function Product({ product }) {
const { addItem } = useShoppingCart()
Expand All @@ -25,7 +24,7 @@ export default function Product({ product }) {
}

return (
<article className="flex flex-col gap-3 bg-white p-8 rounded-xl shadow-md text-center mb-6">
<article className="flex text-black flex-col gap-3 bg-white p-8 rounded-xl shadow-md text-center mb-6">
<div className="text-8xl cursor-default">{emoji}</div>
<div className="text-lg">{name}</div>
<div className="text-2xl font-semibold mt-auto">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useShoppingCart } from "use-shopping-cart";
import CartItem from "./CartItem";
import CheckoutButton from "./CheckoutButton";
import { useShoppingCart } from 'use-shopping-cart'
import CartItem from './CartItem'
import CheckoutButton from './CheckoutButton'

export default function ShoppingCart() {
const { shouldDisplayCart, cartCount, cartDetails } = useShoppingCart();
const { shouldDisplayCart, cartCount, cartDetails } = useShoppingCart()
return (
<div
className={`bg-white flex flex-col absolute right-3 md:right-9 top-14 w-80 py-4 px-4 shadow-[0_5px_15px_0_rgba(0,0,0,.15)] rounded-md transition-opacity duration-500 ${
shouldDisplayCart ? "opacity-100" : "opacity-0"
className={`bg-white text-black flex flex-col absolute right-3 md:right-9 top-14 w-80 py-4 px-4 shadow-[0_5px_15px_0_rgba(0,0,0,.15)] rounded-md transition-opacity duration-500 ${
shouldDisplayCart ? 'opacity-100' : 'opacity-0'
}`}
>
{cartCount && cartCount > 0 ? (
Expand All @@ -21,5 +21,5 @@ export default function ShoppingCart() {
<div className="p-5">You have no items in your cart</div>
)}
</div>
);
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ function CartProvider({ children }) {
return (
<USCProvider
mode="checkout-session"
stripe={'test'}
stripe={process.env.NEXT_PUBLIC_STRIPE_KEY}
currency={'USD'}
successUrl={'https://example.com/success'}
cancelUrl={'https://example.com/cancel'}
allowedCountries={['US', 'GB', 'CA']}
billingAddressCollection={true}
>
Expand All @@ -20,4 +18,3 @@ function CartProvider({ children }) {
}

export default CartProvider

Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ export default function Home() {
</div>
)
}

19 changes: 19 additions & 0 deletions examples/nextjs-app-router/src/app/session/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { stripe } from '../../lib/stripe'
import { headers } from 'next/headers'
import { products } from '../data/products'
import { validateCartItems } from 'use-shopping-cart/utilities'

export async function POST(request) {
const inventory = products
const cartProducts = await request.json()
const line_items = validateCartItems(inventory, cartProducts)
console.log('line_items', line_items)
const checkoutSession = await stripe.checkout.sessions.create({
mode: 'payment',
submit_type: 'pay',
line_items,
success_url: `${headers().get('origin')}/success`,
cancel_url: `${headers().get('origin')}/`
})
return Response.json({ sessionId: checkoutSession.id })
}
9 changes: 9 additions & 0 deletions examples/nextjs-app-router/src/lib/stripe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Stripe from 'stripe'
export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
// https://github.com/stripe/stripe-node#configuration
apiVersion: '2023-08-16',
appInfo: {
name: 'projectname',
url: 'http://localhost:3000/'
}
})
55 changes: 0 additions & 55 deletions examples/nextjs-root-layout/src/app/components/CheckoutButton.js

This file was deleted.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"prepare": "husky install",
"dev:vite-react": "pnpm run bundle && pnpm --filter vite-react run dev",
"dev:nextjs": "pnpm run bundle && pnpm --filter nextjs run dev",
"dev:nextjs-root-layout": "pnpm run bundle && pnpm --filter nextjs-root-layout run dev",
"dev:nextjs-app-router": "pnpm run bundle && pnpm --filter nextjs-app-router run dev",
"dev:typescript-cra": "pnpm run bundle && pnpm --filter typescript-usage run start",
"dev:docs": "pnpm run bundle && pnpm --filter docs run start",
"test": "pnpm --filter use-shopping-cart run test",
Expand All @@ -16,7 +16,6 @@
},
"dependencies": {
"cross-env": "^7.0.3",
"lint-staged": "^10.5.4",
"open-cli": "^6.0.1",
"prettier": "^2.8.4"
},
Expand All @@ -30,7 +29,9 @@
},
"devDependencies": {
"all-contributors-cli": "^6.24.0",
"eslint": "^8.51.0",
"husky": "^8.0.3",
"lint-staged": "^10.5.4",
"typescript": "^4.9.5",
"webpack-dev-server": "4.11.1"
},
Expand All @@ -45,4 +46,3 @@
}
]
}

Loading