├── README.md
└── project
├── .eslintrc.json
├── .gitignore
├── .vscode
└── settings.json
├── README.md
├── data.json
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── next.svg
├── thirteen.svg
└── vercel.svg
├── src
└── app
│ ├── api
│ └── hello
│ │ └── route.ts
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ ├── page.module.css
│ └── page.tsx
├── tailwind.config.js
└── tsconfig.json
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Simplify Frontend Exercise
4 |
5 | Hello! If you're reading this then we're likely in the process of considering you for a role at Simplify. If so, congratulations 🎉 !
6 |
7 | We'd like to know a little more about how you work, so this repository contains a short (approximately 2-3 hours) exercise that you can use demonstrate your skills and abilities.
8 |
9 | We know that 2-3 hours is not a lot of time and you may not be able to complete everything you'd like, and will feel pressure to do more. We're not looking for perfection in the UI and are not evaluating your skills as a designer so be sure to focus on functionality and showing your knowledge of NextJS and React best practices. Of course if time permits, feel free to polish the UI and flex any design skills. Best of luck!
10 |
11 | # Overview
12 |
13 | In this exercise you will be using React, NextJS, and TailwindCSS to make three pages of an ecommerce app. You will be getting familiar with TailwindCSS and exploring the features of NextJS like server-side rendering, app layouts, and dynamic slugs. Your task will be to create pages/components based on the designs from a Figma file, mock an api to provide data to the pages, and follow instructions on which NextJS features to use for the pages.
14 |
15 | The goal of this exercise is to evaulate your ability to:
16 | * translate specs into well organized components
17 | * successfully implement advanced features of NextJS you may be unfamiliar with
18 | * showcase your experience with styling components with TailwindCSS
19 |
20 | # Instructions
21 |
22 | Clone this repo to get started. We've provided a starter project for you with React 18, Typescript, [NextJS 13](https://beta.nextjs.org/docs/getting-started), [TailwindCSS](https://tailwindcss.com/docs/installation), and [SWR](https://swr.vercel.app/docs/getting-started) already added and default configured. Be sure to read through the docs for these libraries if you are unfamiliar. You're also welcome to use any other packages if you'd like, just be sure to explain why you decided to use them and meet all the project requirements with the provided stack.
23 |
24 | 1. Mock ecommerce API
25 |
26 | Using the api route feature in NextJS mock the following routes:
27 | * Getting a list of favorite items
28 | * Getting details of an item from its ID
29 |
30 | We've provided a json file with mock data to use called `data.json`. Feel free to modify it or add to it if you wish. Though we are't expecting you to do error handling, you may add error responses to the api if you have time.
31 |
32 | 2. Make three pages using NextJS App Router format. Implement a root layout and individual layout files where needed.
33 |
34 | The designs for the three pages can be found in this [Figma file](https://www.figma.com/file/lUbwgHr7OTh4IEf1Y4szwf/NextJS-Ecommerce?node-id=0%3A1&t=bHXi1DmZpSYk17Wd-1). Implement the designs, creating components where it makes sense and following best practice organization.
35 |
36 | * `/dashboard/list`
37 | * Following the `List page` design, create a page that uses a top navigation bar layout with the main content showing a list of the user's favorite items.
38 | * Use swr to load the data client side from the mock API you made in step 1. Before the data is loaded, show a loading icon in place of the list.
39 | * The list items do not need to have any functionality other than when clicking on an item it will take you to the /item/[id] page of its id.
40 | * The appearace/UI of the top navigation is not important and does not need to match the design if it is time consuming.
41 | * `/dashboard/card`
42 | * Following the `Card page` design, create a page that uses a side navigation bar layout with the main content showing a grid of cards of the user's favorite items.
43 | * Use swr to load the data client side from the mock API you made in step 1. Before the data is loaded, show a loading icon in place of the grid.
44 | * The card items do not need to have any functionality other than when clicking the View button it will take you to the /item/[id] page of its id.
45 | * The appearace/UI of the top navigation is not important and does not need to match the design if it is time consuming.
46 | * `/item/[id]`
47 | * Following the `Detail page` design, create a page with the Catch-all Segment to show details of a certain item. This page can use either layout configuration (Route groups may be helpful) and does not need to contain all text content from the design.
48 | * This page should be Server-Side Rendered with NextJS - load the items details from the API and pass it to the page.
49 |
50 | # Submission
51 |
52 | When you're done just zip the project and email it back to us -- **be sure to keep your repository private**. Include instructions for running the app locally in the README as well as any additional explanation you'd like to add. If you used any AI tooling during this take home be sure to outline which tools and how you used them.
53 |
--------------------------------------------------------------------------------
/project/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/project/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/project/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 | "typescript.enablePromptUseWorkspaceTsdk": true
4 | }
--------------------------------------------------------------------------------
/project/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | ```
14 |
15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
16 |
17 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
18 |
19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
20 |
21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
22 |
23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
24 |
25 | ## Learn More
26 |
27 | To learn more about Next.js, take a look at the following resources:
28 |
29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
31 |
32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
33 |
34 | ## Deploy on Vercel
35 |
36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
37 |
38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
39 |
--------------------------------------------------------------------------------
/project/data.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "1",
4 | "name": "Airpods",
5 | "price": "200",
6 | "image": "https://images-na.ssl-images-amazon.com/images/I/71zny7BTRlL._AC_SL1500_.jpg",
7 | "active": true,
8 | "seller": "Apple",
9 | "brand": "Apple",
10 | "model": "Airpods",
11 | "color": "White",
12 | "category": "Electronics",
13 | "description": "Quick access to Siri by saying “ Hey Siri ”. Note : If the size of the earbud tips does not match the size of your ear canals or the headset is not worn properly in your ears, you may not obtain the correct sound qualities or call performance. Change the earbud tips to ones that fit more snugly in your ear. More than 24 hours total listening time with the Charging Case. Effortless setup, in-ear detection, and automatic switching for a magical experience. Easily share audio between two sets of AirPods on your iPhone, iPad, iPod touch, or Apple TV"
14 | },
15 | {
16 | "id": "2",
17 | "name": "Apple Watch",
18 | "price": "300",
19 | "image": "https://m.media-amazon.com/images/I/71XMTLtZd5L._AC_UY436_FMwebp_QL65_.jpg",
20 | "active": true,
21 | "seller": "Apple",
22 | "brand": "Apple",
23 | "model": "Apple Watch",
24 | "color": "Black",
25 | "category": "Electronics",
26 | "description": "Apple Watch Series 3 (GPS, 38mm) - Space Gray Aluminium Case with Black Sport Band"
27 | },
28 | {
29 | "id": "3",
30 | "name": "Apple 2022 MacBook Pro",
31 | "price": "1000",
32 | "image": "https://m.media-amazon.com/images/I/61bX2AoGj2L._AC_UY436_FMwebp_QL65_.jpg",
33 | "active": true,
34 | "seller": "Apple",
35 | "brand": "Apple",
36 | "model": "MacBook Pro",
37 | "color": "Grey",
38 | "category": "Electronics",
39 | "description": "SUPERCHARGED BY M2 — The 13-inch MacBook Pro laptop is a portable powerhouse. Get more done faster with a next-generation 8-core CPU, 10-core GPU and up to 24GB of unified memory."
40 | },
41 | {
42 | "id": "4",
43 | "name": "Samsung Galaxy S21 5G",
44 | "price": "270",
45 | "image": "https://m.media-amazon.com/images/I/61jYjeuNUnL._AC_UY436_FMwebp_QL65_.jpg",
46 | "active": true,
47 | "seller": "SAMSUNG",
48 | "brand": "SAMSUNG",
49 | "model": "S21",
50 | "color": "Black",
51 | "category": "Electronics",
52 | "description": "US Model. Compatible with Most GSM and CDMA Carriers like T-Mobile, AT&T, MetroPCS, etc. Will Also work with CDMA Carriers Such as Verizon, Sprint."
53 | },
54 | {
55 | "id": "5",
56 | "name": "SAMSUNG 85 Class Neo QLED 4K",
57 | "price": "2,697",
58 | "image": "https://m.media-amazon.com/images/I/91l0zt+lh3L._AC_SX679_.jpg",
59 | "active": true,
60 | "seller": "SAMSUNG",
61 | "brand": "SAMSUNG",
62 | "model": "4K QN90B",
63 | "color": "Grey",
64 | "category": "Electronics",
65 | "description": "QUANTUM MATRIX WITH MINI LEDs: Brilliant details shine even in daylight; Powered by a huge grid of Samsung’s ultra precise Quantum Mini LEDs, it takes exact control of the individual zones of light in your picture for breathtaking color and contrast"
66 | },
67 | {
68 | "id": "6",
69 | "name": "SAMSUNG Galaxy Buds2",
70 | "price": "76",
71 | "image": "https://m.media-amazon.com/images/I/41kyDAzwbrL._AC_UY436_FMwebp_QL65_.jpg",
72 | "active": true,
73 | "seller": "SAMSUNG",
74 | "brand": "SAMSUNG",
75 | "model": "Galaxy Buds2",
76 | "color": "Black",
77 | "category": "Electronics",
78 | "description": "Your Ears Never Had It So Good: Galaxy Buds2 ear buds take your passion for music to new heights with booming sound that makes you feel like you're on stage with your favorite band"
79 | },
80 | {
81 | "id": "7",
82 | "name": "Beats Studio3 Wireless Noise Cancelling",
83 | "price": "199",
84 | "image": "https://m.media-amazon.com/images/I/51-+O3-wFxL._AC_SX679_.jpg",
85 | "active": false,
86 | "seller": "Beats",
87 | "brand": "Beats",
88 | "model": "Beats Studio3",
89 | "color": "Matte Black",
90 | "category": "Electronics",
91 | "description": "High-performance wireless noise cancelling headphones"
92 | }
93 | ]
--------------------------------------------------------------------------------
/project/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | experimental: {
4 | appDir: true,
5 | },
6 | }
7 |
8 | module.exports = nextConfig
9 |
--------------------------------------------------------------------------------
/project/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-project",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@types/node": "18.15.5",
13 | "@types/react": "18.0.28",
14 | "@types/react-dom": "18.0.11",
15 | "eslint": "9.21.0",
16 | "next": "14.2.24",
17 | "react": "18.3.1",
18 | "react-dom": "18.3.1",
19 | "swr": "2.3.2",
20 | "typescript": "5.8.2"
21 | },
22 | "devDependencies": {
23 | "autoprefixer": "10.4.20",
24 | "eslint-config-next": "15.2.1",
25 | "postcss": "8.5.3",
26 | "tailwindcss": "3.2.7"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/project/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/project/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/src/app/api/hello/route.ts:
--------------------------------------------------------------------------------
1 | export async function GET(request: Request) {
2 | return new Response('Hello, Next.js!')
3 | }
4 |
--------------------------------------------------------------------------------
/project/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SimplifyJobs/frontend-assessment/e715ad329db5ccaab81fd1d9d4a4b7f712803989/project/src/app/favicon.ico
--------------------------------------------------------------------------------
/project/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | :root {
6 | --max-width: 1100px;
7 | --border-radius: 12px;
8 | --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
9 | 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
10 | 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
11 |
12 | --foreground-rgb: 0, 0, 0;
13 | --background-start-rgb: 214, 219, 220;
14 | --background-end-rgb: 255, 255, 255;
15 |
16 | --primary-glow: conic-gradient(
17 | from 180deg at 50% 50%,
18 | #16abff33 0deg,
19 | #0885ff33 55deg,
20 | #54d6ff33 120deg,
21 | #0071ff33 160deg,
22 | transparent 360deg
23 | );
24 | --secondary-glow: radial-gradient(
25 | rgba(255, 255, 255, 1),
26 | rgba(255, 255, 255, 0)
27 | );
28 |
29 | --tile-start-rgb: 239, 245, 249;
30 | --tile-end-rgb: 228, 232, 233;
31 | --tile-border: conic-gradient(
32 | #00000080,
33 | #00000040,
34 | #00000030,
35 | #00000020,
36 | #00000010,
37 | #00000010,
38 | #00000080
39 | );
40 |
41 | --callout-rgb: 238, 240, 241;
42 | --callout-border-rgb: 172, 175, 176;
43 | --card-rgb: 180, 185, 188;
44 | --card-border-rgb: 131, 134, 135;
45 | }
46 |
47 | @media (prefers-color-scheme: dark) {
48 | :root {
49 | --foreground-rgb: 255, 255, 255;
50 | --background-start-rgb: 0, 0, 0;
51 | --background-end-rgb: 0, 0, 0;
52 |
53 | --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
54 | --secondary-glow: linear-gradient(
55 | to bottom right,
56 | rgba(1, 65, 255, 0),
57 | rgba(1, 65, 255, 0),
58 | rgba(1, 65, 255, 0.3)
59 | );
60 |
61 | --tile-start-rgb: 2, 13, 46;
62 | --tile-end-rgb: 2, 5, 19;
63 | --tile-border: conic-gradient(
64 | #ffffff80,
65 | #ffffff40,
66 | #ffffff30,
67 | #ffffff20,
68 | #ffffff10,
69 | #ffffff10,
70 | #ffffff80
71 | );
72 |
73 | --callout-rgb: 20, 20, 20;
74 | --callout-border-rgb: 108, 108, 108;
75 | --card-rgb: 100, 100, 100;
76 | --card-border-rgb: 200, 200, 200;
77 | }
78 | }
79 |
80 | * {
81 | box-sizing: border-box;
82 | padding: 0;
83 | margin: 0;
84 | }
85 |
86 | html,
87 | body {
88 | max-width: 100vw;
89 | overflow-x: hidden;
90 | }
91 |
92 | body {
93 | color: rgb(var(--foreground-rgb));
94 | background: linear-gradient(
95 | to bottom,
96 | transparent,
97 | rgb(var(--background-end-rgb))
98 | )
99 | rgb(var(--background-start-rgb));
100 | }
101 |
102 | a {
103 | color: inherit;
104 | text-decoration: none;
105 | }
106 |
107 | @media (prefers-color-scheme: dark) {
108 | html {
109 | color-scheme: dark;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/project/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import "./globals.css";
2 |
3 | export const metadata = {
4 | title: "Create Next App",
5 | description: "Generated by create next app",
6 | };
7 |
8 | export default function RootLayout({
9 | children,
10 | }: {
11 | children: React.ReactNode;
12 | }) {
13 | return (
14 |
15 |