69 | >
70 | )
71 | }
72 |
73 | export async function getStaticPaths () {
74 | const inventory = await fetchInventory()
75 | const paths = inventory.map(item => {
76 | return { params: { name: slugify(item.name) }}
77 | })
78 | return {
79 | paths,
80 | fallback: false
81 | }
82 | }
83 |
84 | export async function getStaticProps ({ params }) {
85 | const name = params.name.replace(/-/g," ")
86 | const inventory = await fetchInventory()
87 | const product = inventory.find(item => slugify(item.name) === slugify(name))
88 |
89 | return {
90 | props: {
91 | product,
92 | }
93 | }
94 | }
95 |
96 | function ItemViewWithContext(props) {
97 | return (
98 |
99 |
100 | {
101 | context =>
102 | }
103 |
104 |
105 | )
106 | }
107 |
108 | export default ItemViewWithContext
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/favicon.ico
--------------------------------------------------------------------------------
/public/fonts/Eina-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/fonts/Eina-Light.otf
--------------------------------------------------------------------------------
/public/fonts/Eina-SemiBold.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/fonts/Eina-SemiBold.otf
--------------------------------------------------------------------------------
/public/fonts/Eina-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/fonts/Eina-SemiBold.ttf
--------------------------------------------------------------------------------
/public/fonts/Eina.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/fonts/Eina.otf
--------------------------------------------------------------------------------
/public/fonts/Eina.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/fonts/Eina.ttf
--------------------------------------------------------------------------------
/public/fonts/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Eina";
3 | src: url("Eina.otf");
4 | }
5 |
6 | @font-face {
7 | font-family: "Eina Bold";
8 | src: url("Eina-SemiBold.otf");
9 | }
10 |
11 | @font-face {
12 | font-family: "Eina Light";
13 | src: url("Eina-Light.otf");
14 | }
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/logo.png
--------------------------------------------------------------------------------
/public/products/chair1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair1.png
--------------------------------------------------------------------------------
/public/products/chair10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair10.png
--------------------------------------------------------------------------------
/public/products/chair2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair2.png
--------------------------------------------------------------------------------
/public/products/chair3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair3.png
--------------------------------------------------------------------------------
/public/products/chair4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair4.png
--------------------------------------------------------------------------------
/public/products/chair5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair5.png
--------------------------------------------------------------------------------
/public/products/chair6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair6.png
--------------------------------------------------------------------------------
/public/products/chair7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair7.png
--------------------------------------------------------------------------------
/public/products/chair8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair8.png
--------------------------------------------------------------------------------
/public/products/chair9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/chair9.png
--------------------------------------------------------------------------------
/public/products/couch1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch1.png
--------------------------------------------------------------------------------
/public/products/couch10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch10.png
--------------------------------------------------------------------------------
/public/products/couch11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch11.png
--------------------------------------------------------------------------------
/public/products/couch12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch12.png
--------------------------------------------------------------------------------
/public/products/couch13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch13.png
--------------------------------------------------------------------------------
/public/products/couch14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch14.png
--------------------------------------------------------------------------------
/public/products/couch15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch15.png
--------------------------------------------------------------------------------
/public/products/couch2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch2.png
--------------------------------------------------------------------------------
/public/products/couch3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch3.png
--------------------------------------------------------------------------------
/public/products/couch4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch4.png
--------------------------------------------------------------------------------
/public/products/couch5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch5.png
--------------------------------------------------------------------------------
/public/products/couch6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch6.png
--------------------------------------------------------------------------------
/public/products/couch7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch7.png
--------------------------------------------------------------------------------
/public/products/couch8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch8.png
--------------------------------------------------------------------------------
/public/products/couch9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jamstack-cms/jamstack-ecommerce/64e01be0aea19f09973e8c0ad60129f88278830d/public/products/couch9.png
--------------------------------------------------------------------------------
/serverless.yml:
--------------------------------------------------------------------------------
1 | nextEcommerce:
2 | component: "@sls-next/serverless-component@1.18.0"
3 | # inputs:
4 | # domain: "yourdomain.com"
--------------------------------------------------------------------------------
/snippets/lambda.js:
--------------------------------------------------------------------------------
1 | // https://stripe.com/docs/payments/without-card-authentication
2 | const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY) //"API_KEY"
3 |
4 | exports.handler = async event => {
5 | if (!event.body || event.httpMethod !== "POST") {
6 | return {
7 | statusCode: 400,
8 | headers,
9 | body: JSON.stringify({
10 | status: "invalid http method",
11 | }),
12 | }
13 | }
14 |
15 | const order = JSON.parse(event.body)
16 |
17 | const calculateOrderAmount = items => {
18 | // Replace this constant with a calculation of the order's amount
19 | // You should always calculate the order total on the server to prevent
20 | // people from directly manipulating the amount on the client
21 | return 1400
22 | }
23 |
24 | try {
25 | const intent = await stripe.paymentIntents.create({
26 | amount: calculateOrderAmount(order.items),
27 | currency: "usd",
28 | payment_method: order.payment_method_id,
29 |
30 | // A PaymentIntent can be confirmed some time after creation,
31 | // but here we want to confirm (collect payment) immediately.
32 | confirm: true,
33 |
34 | // If the payment requires any follow-up actions from the
35 | // customer, like two-factor authentication, Stripe will error
36 | // and you will need to prompt them for a new payment method.
37 | error_on_requires_action: true,
38 | })
39 |
40 | if (intent.status === "succeeded") {
41 | // This creates a new Customer and attaches the PaymentMethod in one API call.
42 | const customer = await stripe.customers.create({
43 | payment_method: intent.payment_method,
44 | email: order.email,
45 | address: order.address,
46 | })
47 | // Handle post-payment fulfillment
48 | console.log(`Created Payment: ${intent.id} for Customer: ${customer.id}`)
49 | // Now ship those goodies
50 | await inventoryAPI.ship(order)
51 | } else {
52 | // Any other status would be unexpected, so error
53 | console.log({ error: "Unexpected status " + intent.status })
54 | }
55 | } catch (e) {
56 | if (e.type === "StripeCardError") {
57 | // Display error to customer
58 | console.log({ error: e.message })
59 | } else {
60 | // Something else happened
61 | console.log({ error: e.type })
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | /* ./styles/globals.css */
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
5 |
6 | @font-face {
7 | font-family: "Eina";
8 | src: url("/fonts/Eina.otf");
9 | }
10 |
11 |
12 | @font-face {
13 | font-family: "Eina Light";
14 | src: url("/fonts/Eina-Light.otf");
15 | }
16 |
17 | @font-face {
18 | font-family: "Eina SemiBold";
19 | src: url("/fonts/Eina-SemiBold.otf");
20 | }
21 |
22 | @layer base {
23 | p, h1, h2, h3, h4, h5 {
24 | color: rgba(0, 0, 0, .8);
25 | font-family: Eina;
26 | }
27 | }
28 |
29 | .Toastify__progress-bar--default {
30 | background: #89bdf9 !important;
31 | }
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | // purge: ['./pages/**/*.js', './components/**/*.js'],
3 | darkMode: false, // or 'media' or 'class'
4 | theme: {
5 | extend: {
6 | spacing: {
7 | "72": "18rem",
8 | "80": "20rem",
9 | "88": "22rem",
10 | "96": "24rem",
11 | "104": "26rem",
12 | "112": "28rem",
13 | "120": "30rem",
14 | "124": "31rem",
15 | "128": "32rem",
16 | "132": "33rem",
17 | "136": "34rem",
18 | "140": "35rem",
19 | "144": "36rem",
20 | "fw": "1440px",
21 | },
22 | fontSize: {
23 | 'xxs': '.6rem',
24 | 'smaller': '.95rem'
25 | },
26 | fontFamily: {
27 | 'light': ['Eina Light'],
28 | 'semibold': ['Eina SemiBold'],
29 | },
30 | screens: {
31 | 'mobile': '600px',
32 | 'c_large': '1200px',
33 | 'desktop': '1440px'
34 | },
35 | width: {
36 | '28': '7rem',
37 | 'c_large': '1200px',
38 | "38":"10rem",
39 | "48":"12rem",
40 | "52":"13rem",
41 | "56":"14rem",
42 | "60":"15rem",
43 | "64": "16rem",
44 | "68": "17rem",
45 | "72": "18rem",
46 | "80": "20rem",
47 | "88": "22rem",
48 | "96": "24rem",
49 | "104": "26rem",
50 | "112": "28rem",
51 | "120": "30rem",
52 | "124": "31rem",
53 | "128": "32rem",
54 | "132": "33rem",
55 | "136": "34rem",
56 | "140": "35rem",
57 | "144": "36rem",
58 | 'flex-half': "calc((100%/2) - 15px)",
59 | 'flex-fourth': "calc((100% / 4) - 20px)"
60 | },
61 | inset: {
62 | 'flexiblemargin': "calc((100vw - 1420px) / 2)",
63 | '100': '100px',
64 | '200': '200px',
65 | '250': '250px',
66 | '300': '300px',
67 | '400': '400px',
68 | '20': '20px',
69 | '22': '22px',
70 | '24': '24px',
71 | '26': '26px',
72 | '28': '28px',
73 | '30': '30px',
74 | '35': '35px',
75 | '40': '40px',
76 | '45': '45px',
77 | '45': '45px',
78 | '46': '46px',
79 | '47': '47px',
80 | '48': '48px',
81 | '49': '49px',
82 | '50': '50px',
83 | '51': '51px',
84 | '52':'52px',
85 | '53': '53px',
86 | '54':'54px',
87 | '55': '55px',
88 | '60': '60px'
89 | },
90 | height: {
91 | 'hero': '500px',
92 | "48":"12rem",
93 | "52":"13rem",
94 | "56":"14rem",
95 | "60":"15rem",
96 | "64": "16rem",
97 | "68":"17rem",
98 | "72": "18rem",
99 | "80": "20rem",
100 | "88": "22rem",
101 | "96": "24rem",
102 | "104": "26rem",
103 | "112": "28rem",
104 | "120": "30rem",
105 | "124": "31rem",
106 | "128": "32rem",
107 | "132": "33rem",
108 | "136": "34rem",
109 | "140": "35rem",
110 | "144": "36rem",
111 | },
112 | padding: {
113 | ".5": ".125rem"
114 | },
115 | maxWidth: {
116 | "48":"12rem",
117 | "52":"13rem",
118 | "56":"14rem",
119 | "60":"15rem",
120 | "64": "16rem",
121 | "68":"17rem",
122 | "72": "18rem",
123 | "80": "20rem",
124 | "88": "22rem",
125 | "96": "24rem",
126 | "104": "26rem",
127 | "112": "28rem",
128 | "120": "30rem",
129 | "124": "31rem",
130 | "128": "32rem",
131 | "132": "33rem",
132 | "136": "34rem",
133 | "140": "35rem",
134 | "144": "36rem",
135 | "fw": "1440px",
136 | 'c_large': '1200px'
137 | },
138 | maxHeight: {
139 | "36":"9rem",
140 | "40":"10rem",
141 | "44":"11rem",
142 | "48":"12rem",
143 | "52":"13rem",
144 | "56":"14rem",
145 | "60":"15rem",
146 | "64": "16rem",
147 | "68":"17rem",
148 | "72": "18rem",
149 | "80": "20rem",
150 | "88": "22rem",
151 | "96": "24rem",
152 | "104": "26rem",
153 | "112": "28rem",
154 | "120": "30rem",
155 | "124": "31rem",
156 | "128": "32rem",
157 | "132": "33rem",
158 | "136": "34rem",
159 | "140": "35rem",
160 | "144": "36rem",
161 | "fw": "1440px"
162 | },
163 | zIndex: {
164 | '-2': '-2',
165 | '-4': '-4',
166 | '-6': '-6',
167 | '-12': '-12',
168 | },
169 | backgroundColor: {
170 | 'primary': '#89bdf9',
171 | 'light': '#f5f5f5',
172 | 'light-200': '#f0f0f0',
173 | 'light-300': '#e8e8e8'
174 | },
175 | lineHeight: {
176 | 'large': '54px'
177 | }
178 | },
179 | },
180 | plugins: [],
181 | }
--------------------------------------------------------------------------------
/theme.js:
--------------------------------------------------------------------------------
1 | const colors = {
2 | primary: '#89bdf9'
3 | }
4 |
5 | export {
6 | colors
7 | }
--------------------------------------------------------------------------------
/utils/categoryProvider.js:
--------------------------------------------------------------------------------
1 | import inventory from './inventory'
2 |
3 | async function fetchCategories () {
4 | const categories = inventory.reduce((acc, next) => {
5 | next.categories.map(category => {
6 | if (acc.includes(category)) return
7 | acc.push(category)
8 | })
9 | return acc
10 | }, [])
11 | return Promise.resolve(categories)
12 | }
13 |
14 | export default fetchCategories
--------------------------------------------------------------------------------
/utils/currencyProvider.js:
--------------------------------------------------------------------------------
1 | const DENOMINATION = '$'
2 |
3 | export default DENOMINATION
--------------------------------------------------------------------------------
/utils/helpers.js:
--------------------------------------------------------------------------------
1 | function slugify(string) {
2 | const a = 'àáäâãåăæąçćčđďèéěėëêęğǵḧìíïîįłḿǹńňñòóöôœøṕŕřßşśšșťțùúüûǘůűūųẃẍÿýźžż·/_,:;'
3 | const b = 'aaaaaaaaacccddeeeeeeegghiiiiilmnnnnooooooprrsssssttuuuuuuuuuwxyyzzz------'
4 | const p = new RegExp(a.split('').join('|'), 'g')
5 |
6 | return string.toString().toLowerCase()
7 | .replace(/\s+/g, '-') // Replace spaces with -
8 | .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters
9 | .replace(/&/g, '-and-') // Replace & with 'and'
10 | .replace(/[^\w-]+/g, '') // Remove all non-word characters
11 | .replace(/--+/g, '-') // Replace multiple - with single -
12 | .replace(/^-+/, '') // Trim - from start of text
13 | .replace(/-+$/, '') // Trim - from end of text
14 | }
15 |
16 | function titleIfy(slug) {
17 | var words = slug.split('-')
18 | for (var i = 0; i < words.length; i++) {
19 | var word = words[i]
20 | words[i] = word.charAt(0).toUpperCase() + word.slice(1)
21 | }
22 | return words.join(' ')
23 | }
24 |
25 | function getTrimmedString(string, length = 8) {
26 | if (string.length <= length) {
27 | return string
28 | } else {
29 | return string.substring(0, length) + '...'
30 | }
31 | }
32 |
33 | export {
34 | slugify, titleIfy, getTrimmedString
35 | }
--------------------------------------------------------------------------------
/utils/inventory.js:
--------------------------------------------------------------------------------
1 | import { v4 as uuid } from 'uuid'
2 |
3 | let inventory = [
4 | {
5 | categories: ['new arrivals'], name: 'Timber Gray Sofa 2.0', price: '1000', image: '/products/couch1.png', description: 'Stay a while. The Timber charme chocolat sofa is set atop an oak trim and flaunts fluffy leather back and seat cushions. Over time, this brown leather sofa’s full-aniline upholstery will develop a worn-in vintage look. Snuggle up with your cutie (animal or human) and dive into a bowl of popcorn. This sofa is really hard to leave. Natural color variations, wrinkles and creases are part of the unique characteristics of this leather. It will develop a relaxed vintage look with regular use.', brand: 'Jason Bourne', currentInventory: 4 },
6 | {
7 | categories: ['sofas', 'living room'], name: 'Carmel Brown Sofa', price: '1000', image: '/products/couch5.png', description: 'Stay a while. The Timber charme chocolat sofa is set atop an oak trim and flaunts fluffy leather back and seat cushions. Over time, this brown leather sofa’s full-aniline upholstery will develop a worn-in vintage look. Snuggle up with your cutie (animal or human) and dive into a bowl of popcorn. This sofa is really hard to leave. Natural color variations, wrinkles and creases are part of the unique characteristics of this leather. It will develop a relaxed vintage look with regular use.' , brand: 'Jason Bourne' , currentInventory: 2 },
8 | {
9 | categories: ['new arrivals', 'sofas'], name: 'Mod Leather Sofa', price: '800', image: '/products/couch6.png', description: 'Easy to love. The Sven in birch ivory looks cozy and refined, like a sweater that a fancy lady wears on a coastal vacation. This ivory loveseat has a tufted bench seat, loose back pillows and bolsters, solid walnut legs, and is ready to make your apartment the adult oasis you dream of. Nestle it with plants, an ottoman, an accent chair, or 8 dogs. Your call.', brand: 'Jason Bourne', currentInventory: 8 },
10 | {
11 | categories: ['new arrivals', 'sofas'], name: 'Thetis Gray Love Seat', price: '900', image: '/products/couch7.png', description: 'You know your dad’s incredible vintage bomber jacket? The Nirvana dakota tan leather sofa is that jacket, but in couch form. With super-plush down-filled cushions, a corner-blocked wooden frame, and a leather patina that only gets better with age, the Nirvana will have you looking cool and feeling peaceful every time you take a seat. Looks pretty great with a sheepskin throw, if we may say so. With use, this leather will become softer and more wrinkled and the cushions will take on a lived-in look, like your favorite leather jacket.' , brand: 'Jason Bourne', currentInventory: 10},
12 | {
13 | categories: ['on sale', 'sofas'], name: 'Sven Tan Matte', price: '1200', image: '/products/couch8.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne' , currentInventory: 7 },
14 | {
15 | categories: ['on sale', 'sofas'], name: 'Otis Malt Sofa', price: '500', image: '/products/couch9.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 13},
16 | {
17 | categories: ['on sale', 'sofas'], name: 'Ceni Brown 3 Seater', price: '650', image: '/products/couch10.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 9},
18 | {
19 | categories: ['sofas', 'living room'], name: 'Jameson Jack Lounger', price: '1230', image: '/products/couch11.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 24 },
20 |
21 | {
22 | categories: ['sofas'], name: 'Galaxy Blue Sofa', price: '800', image: '/products/couch2.png', description: 'Easy to love. The Sven in birch ivory looks cozy and refined, like a sweater that a fancy lady wears on a coastal vacation. This ivory loveseat has a tufted bench seat, loose back pillows and bolsters, solid walnut legs, and is ready to make your apartment the adult oasis you dream of. Nestle it with plants, an ottoman, an accent chair, or 8 dogs. Your call.', brand: 'Jason Bourne', currentInventory: 43 },
23 | {
24 | categories: ['new arrivals', 'sofas'], name: 'Markus Green Love Seat', price: '900', image: '/products/couch3.png', description: 'You know your dad’s incredible vintage bomber jacket? The Nirvana dakota tan leather sofa is that jacket, but in couch form. With super-plush down-filled cushions, a corner-blocked wooden frame, and a leather patina that only gets better with age, the Nirvana will have you looking cool and feeling peaceful every time you take a seat. Looks pretty great with a sheepskin throw, if we may say so. With use, this leather will become softer and more wrinkled and the cushions will take on a lived-in look, like your favorite leather jacket.', brand: 'Jason Bourne' , currentInventory: 2},
25 | {
26 | categories: ['on sale', 'sofas'], name: 'Dabit Matte Black', price: '1200', image: '/products/couch4.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', currentInventory: 14 },
27 |
28 | {
29 | categories: ['on sale', 'chairs'], name: 'Embrace Blue', price: '300', image: '/products/chair1.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 12 },
30 | {
31 | categories: ['on sale', 'chairs'], name: 'Nord Lounger', price: '825', image: '/products/chair2.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 13},
32 | {
33 | categories: ['on sale', 'chairs'], name: 'Ceni Matte Oranve', price: '720', image: '/products/chair3.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 33},
34 | {
35 | categories: ['on sale', 'chairs'], name: 'Abisko Green Recliner', price: '2000', image: '/products/chair4.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 23 },
36 | { categories: ['on sale', 'chairs'], name: 'Denim on Denim Single', price: '1100', image: '/products/chair5.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.' , brand: 'Jason Bourne', currentInventory: 13},
37 | { categories: ['on sale', 'chairs'], name: 'Levo Tan Lounge Chair', price: '600', image: '/products/chair6.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 15 },
38 |
39 | { categories: ['on sale', 'chairs'], name: 'Anime Tint Recliner', price: '775', image: '/products/chair7.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 44 },
40 | { categories: ['on sale', 'chairs'], name: 'Josh Jones Red Chair', price: '1200', image: '/products/chair8.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 17 },
41 | { categories: ['on sale', 'chairs'], name: 'Black Sand Lounge', price: '1600', image: '/products/chair9.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 28 },
42 | { categories: ['on sale', 'chairs'], name: 'Mint Beige Workchair', price: '550', image: '/products/chair10.png', description: 'You don’t have to go outside to be rugged. The Cigar rawhide sofa features a sturdy corner-blocked wooden frame and raw seams for that Malboro-person look. This brown leather sofa is cozy in a cottage, cabin, or a condo. And the leather (the leather!) becomes more beautiful with use: subtle character markings such as insect bites, healed scars, and grain variation reflects a real vintage. Saddle up and pass the remote.', brand: 'Jason Bourne', currentInventory: 31 }, // {
43 | ]
44 |
45 | inventory.map(i => {
46 | i.id = uuid()
47 | return i
48 | })
49 |
50 | export default inventory
--------------------------------------------------------------------------------
/utils/inventoryByCategory.js:
--------------------------------------------------------------------------------
1 | function inventoryByCategory (inventory) {
2 | return inventory.reduce((acc, next) => {
3 | const categories = next.categories
4 | categories.forEach(c => {
5 | if (acc[c]) {
6 | acc[c].items.push(next)
7 | } else {
8 | acc[c] = {}
9 | acc[c].items = []
10 | acc[c].items.push(next)
11 | }
12 | })
13 | return acc
14 | }, {})
15 | }
16 |
17 | export {
18 | inventoryByCategory
19 | }
--------------------------------------------------------------------------------
/utils/inventoryForCategory.js:
--------------------------------------------------------------------------------
1 | import { fetchInventory } from './inventoryProvider'
2 | import { inventoryByCategory } from './inventoryByCategory'
3 |
4 | async function inventoryForCategory (category) {
5 | const inventory = await fetchInventory()
6 | const byCategory = inventoryByCategory(inventory)
7 | return byCategory[category].items
8 | }
9 |
10 | export default inventoryForCategory
--------------------------------------------------------------------------------
/utils/inventoryProvider.js:
--------------------------------------------------------------------------------
1 | import inventory from './inventory'
2 |
3 | /*
4 | Inventory items should adhere to the following schema:
5 | type Product {
6 | id: ID!
7 | categories: [String]!
8 | price: Float!
9 | name: String!
10 | image: String!
11 | description: String!
12 | currentInventory: Int!
13 | brand: String
14 | sku: ID
15 | }
16 | */
17 |
18 | async function fetchInventory() {
19 | // const inventory = API.get(apiUrl)
20 | return Promise.resolve(inventory)
21 | }
22 |
23 | export {
24 | fetchInventory, inventory as staticInventory
25 | }
--------------------------------------------------------------------------------