diff --git a/app/(pages)/(app)/products/create/_components/AboutPage.tsx b/app/(pages)/(app)/products/create/_components/AboutPage.tsx new file mode 100644 index 0000000..7f6137c --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/AboutPage.tsx @@ -0,0 +1,135 @@ +'use client'; +import styles from './CreateProductForm.module.scss'; +import Image from 'next/image'; +import React, { useState } from 'react'; +import Textbox from '@components/Textbox/Textbox'; +// import ShortInput from '@components/ShortInput/ShortInput'; + +export default function AboutPage() { + const [tags, setTags] = useState([]); + const addTag = (event: React.KeyboardEvent) => { + event.preventDefault(); + const input = event.target as HTMLInputElement; + const newTag = input.value; + if (newTag !== '') { + setTags((prevTags) => [...prevTags, newTag]); + } + input.value = ''; + }; + const deleteTag = (index: number) => { + setTags((prevTags) => [ + ...prevTags.slice(0, index), + ...prevTags.slice(index + 1), + ]); + }; + const [types, setTypes] = useState([]); + const addType = (event: React.KeyboardEvent) => { + event.preventDefault(); + const input = event.target as HTMLInputElement; + const newType = input.value; + if (newType !== '') { + setTypes((prevTypes) => [...prevTypes, newType]); + } + input.value = ''; + }; + const deleteType = (index: number) => { + setTypes((prevTypes) => [ + ...prevTypes.slice(0, index), + ...prevTypes.slice(index + 1), + ]); + }; + const [formData, setFormData] = useState({ + title: '', + description: '', + }); + const handleInputChange = (event: React.ChangeEvent) => { + const { name, value } = event.target; + setFormData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + return ( +
+ {/* Title - Text Box, Category - Text Box + Description - Larger Text Box + Product Type - Dropdown selector, Tags - Dropdown selector + Media - Image Uploading (placholder) */} +
+
+
+

Title

+ +
+
+

Category

+ +
+
+
+

Description

+ +
+
+

Product Type

{/* unlink from tags section */} + ) => { + if (event.key === 'Enter') { + addType(event); + } + }} + id="type_search" + type="text" + placeholder="Watch.." + /> +
+ {types.map((type, index) => ( +

+ {type} deleteType(index)}>x +

+ ))} +
+
+
+

Tags

+ ) => { + if (event.key === 'Enter') { + addTag(event); + } + }} + id="tags_search" + type="text" + placeholder="Watch.." + /> +
+ {tags.map((tag, index) => ( +

+ {tag} deleteTag(index)}>x +

+ ))} +
+
+
+

Media

+
+
+ upload icon +

Drag and Drop here

+

or

+ +
+
+
+ ); +} diff --git a/app/(pages)/(app)/products/create/_components/CarriersPage.tsx b/app/(pages)/(app)/products/create/_components/CarriersPage.tsx new file mode 100644 index 0000000..613626f --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/CarriersPage.tsx @@ -0,0 +1,11 @@ +'use client'; +import styles from './CreateProductForm.module.scss'; + +export default function CarriersPage() { + return ( +
+

Carriers Information

+

Placeholder

+
+ ); +} diff --git a/app/(pages)/(app)/products/create/_components/CreateProductForm.module.scss b/app/(pages)/(app)/products/create/_components/CreateProductForm.module.scss new file mode 100644 index 0000000..c39dc52 --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/CreateProductForm.module.scss @@ -0,0 +1,307 @@ +@use 'media'; + +.container{ + display: flex; + flex-direction: column; +} + +.header { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + width: 60%; + margin: auto; +} + +.navbar { + display: flex; + position: relative; + justify-content: space-between; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 3px; + background-color: #e9e8e8; + z-index: 1; + } +} + +.navItem { + flex: 1; + text-align: center; + padding: 0.8rem 0; + cursor: pointer; + color: #333; + transition: color 0.3s ease; + + &:hover { + color: var(--purple); + } +} + +.activeIndicator { + position: absolute; + bottom: 0; + left: 0; + height: 3px; + width: 25%; + background-color: var(--purple); + z-index: 2; + transition: transform 0.3s ease; +} + +.content { + margin-top: 1rem; + padding: 1rem; + + h4 { + font-weight: bold; + } + + p { + margin: 0; + } +} + +.listing { + width: 60%; + display: flex; + flex-direction: column; + margin: auto; + justify-content: center; + padding: var(--small-spacer); + text-align: left; + color: var(--text-light); + border-style: solid; + border-width: 2px; + background-color: transparent; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.374); +} + +.title { + width: 60%; + justify-content: center; + //margin: auto; + padding: var(--small-spacer); + text-align: left; +} + +.subpage_container{ + .img_container { + padding: var(--large-spacer) var(--medium-spacer); + margin-bottom: var(--medium-spacer); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: var(--tiny-spacer); + background-color: var(--background-upload); + border-style: dashed; + border-width: 1px; + border-color: var(--gray-500); + border-radius: var(--tiny-spacer); + + p { + font-size: 80%; + font-weight: 500; + } + + .purple_button { + padding: var(--tiny-spacer) var(--small-spacer); + font-size: 80%; + } + } + + .inputs_container { + + .row_container { + display: grid; + grid-template-columns: 1fr 1fr; + row-gap: 1em; + gap: var(--small-spacer); + + } + + .special_row_container{ + display: flex; + grid-template-columns: 1fr 1fr 1fr; + gap: var(--small-spacer); + } + + .column_container { + display: flex; + flex-direction: column; + gap: var(--tiny-spacer); + + @include media.phone { + gap: var(--tiny-spacer); + } + + input { + width: 100%; + + @include media.phone { + width: 100%; + } + } + } + + + .input_container { + width: 100%; + padding: var(--tiny-spacer) 0; + } + + input { + width: 100%; + padding: var(--small-spacer) var(--small-spacer); + margin: var(--tiny-spacer) 0; + border-style: solid; + border-width: 1px; + border-color: var(--gray-500); + border-radius: var(--tiny-spacer); + outline: none; + } + + input::placeholder { + color: var(--gray-500); + } + + p { + font-size: 90%; + font-weight: 500; + } + + h4 { + padding: var(--small-spacer) 0; + } + } + + .selected_tags { + display: flex; + flex-direction: row; + justify-content: flex-start; + align-content: flex-start; + flex-wrap: wrap; + overflow: scroll; + scrollbar-width: none; + gap: var(--tiny-spacer); + border: solid; + border-color: var(--gray-500); + border-width: 1px; + border-radius: var(--tiny-spacer); + padding: var(--small-spacer); + height: 160px; + + .tag_display { + align-self: flex-start; + border: solid; + border-color: var(--gray-500); + border-width: 1px; + border-radius: 3px; + padding: var(--tiny-spacer) var(--small-spacer); + font-size: 90%; + font-weight: 500; + } + + span { + color: var(--gray-500); + margin-left: var(--tiny-spacer); + cursor: pointer; + } + } +} + +.button_container { + display: flex; + flex-direction: row; + justify-content: right; + align-items: center; + gap: var(--small-spacer); + + @include media.phone { + flex-direction: column; + } +} + +.white_button { + padding: var(--tiny-spacer) var(--medium-spacer); + border: none; + border-radius: var(--tiny-spacer); + cursor: pointer; + background-color: var(--background-secondary); + color: var(--purple); + font-weight: 500; + border-style: solid; + border-width: 1px; + border-color: var(--gray-300); +} + +.purple_button { + padding: var(--tiny-spacer) var(--medium-spacer); + border: none; + border-radius: var(--tiny-spacer); + cursor: pointer; + background-color: var(--purple); + color: var(--text-light); + font-weight: 500; +} + +.delete_button { + padding: var(--tiny-spacer) var(--medium-spacer); + border: none; + border-radius: var(--tiny-spacer); + cursor: pointer; + background-color: transparent; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); +} + +.toggle_container { + display: flex; + align-items: center; + gap: var(--small-spacer); + + .toggle { + appearance: none; + display: inline-block; + max-width: 64px; + min-width: 64px; + position: relative; + border-radius: 50px; + outline: none; + overflow: hidden; + cursor: pointer; + height: 32px; + background-color: var(--background-secondary); + transition: background-color ease 0.3s; + } + + .toggle:before { + content: ""; + display: block; + position: absolute; + z-index: 2; + width: 28px; + height: 28px; + background: var(--gray-500); + left: 2px; + top: 2px; + border-radius: 50px; + color: var(--gray-500); + transition: all cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s; + } + + .toggle:checked { + background-color: var(--background-tertiary); + } + + .toggle:checked:before { + left: 32px; + } +} \ No newline at end of file diff --git a/app/(pages)/(app)/products/create/_components/CreateProductForm.tsx b/app/(pages)/(app)/products/create/_components/CreateProductForm.tsx new file mode 100644 index 0000000..f8eec43 --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/CreateProductForm.tsx @@ -0,0 +1,97 @@ +'use client'; +import styles from './CreateProductForm.module.scss'; +import React, { useState } from 'react'; +import { FormEvent } from 'react'; +import AboutPage from './AboutPage'; +import DetailsPage from './DetailsPage'; +import ShippingPage from './ShippingPage'; +import CarriersPage from './CarriersPage'; + +const ItemsBar = ({ + items, + activeIndex, + onTabChange, +}: { + items: string[]; + activeIndex: number; + onTabChange: (index: number) => void; +}) => { + return ( + + ); +}; + +export default function CreateProductForm() { + const [activeTab, setActiveTab] = useState(0); + + const handleSubmit = (event: FormEvent) => { + event.preventDefault(); + console.log('Form submitted'); + }; + + const renderContent = () => { + switch (activeTab) { + case 0: + return ; + case 1: + return ; + case 2: + return ; + case 3: + return ; + default: + return null; + } + }; + + return ( +
+
+
+

Create Product

+
+
+ +
+
+
+ +
+
{renderContent()}
+
+ + +
+
+
+
+ ); +} diff --git a/app/(pages)/(app)/products/create/_components/DetailsPage.tsx b/app/(pages)/(app)/products/create/_components/DetailsPage.tsx new file mode 100644 index 0000000..e9c361b --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/DetailsPage.tsx @@ -0,0 +1,78 @@ +'use client'; +import styles from './CreateProductForm.module.scss'; +import Image from 'next/image'; +import React, { useState } from 'react'; + +export default function DetailsPage() { + const [formData] = useState({ + title: '', + description: '', + }); + return ( +
+
+ {/* Title - Shows input from About + Description - Shows input from About + Pricing - Text box, Processing Time - Text box + Item Weight (Prepared for Packing) - 2 Text boxes (one for lbs, one for oz) + Length - Text box, Width - Text box, Height - Text box */} +
+

+ {formData.title} +

+

{formData.description}

+
+
+ upload icon +
+
+
+
+

Pricing

+ +
+
+

Processing Time

+ +
+
+
+
+
+
+

Item Weight (Prepared for Packing)

+ +
+
+

+

+

+ +
+
+
+
+
+
+

Length

+ +
+
+

Width

+ +
+
+

Height

+ +
+
+
+
+
+ ); +} diff --git a/app/(pages)/(app)/products/create/_components/ShippingPage.tsx b/app/(pages)/(app)/products/create/_components/ShippingPage.tsx new file mode 100644 index 0000000..9f6ac37 --- /dev/null +++ b/app/(pages)/(app)/products/create/_components/ShippingPage.tsx @@ -0,0 +1,11 @@ +'use client'; +import styles from './CreateProductForm.module.scss'; + +export default function ShippingPagge() { + return ( +
+

Shipping Information

+

Placeholder

+
+ ); +} diff --git a/app/(pages)/(app)/products/create/page.tsx b/app/(pages)/(app)/products/create/page.tsx new file mode 100644 index 0000000..6f53b27 --- /dev/null +++ b/app/(pages)/(app)/products/create/page.tsx @@ -0,0 +1,9 @@ +import CreateProductForm from './_components/CreateProductForm'; + +export default function CreateProductPage() { + return ( +
+ +
+ ); +} diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss deleted file mode 100644 index dbba5eb..0000000 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ /dev/null @@ -1,212 +0,0 @@ -@use 'media'; - -.container { - width: 60%; - display: flex; - flex-direction: column; - justify-content: center; - padding: var(--medium-spacer); - text-align: left; - background-color: var(--secondary); - background-color: var(--background-secondary); - color: var(--text-light); - border-style: solid; - border-width: 2px; // change from hard code - border-color: var(--gray-100); -} - -.img_container { - padding: var(--large-spacer) var(--medium-spacer); - margin-bottom: var(--medium-spacer); - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: var(--tiny-spacer); - background-color: var(--background-upload); - border-style: dashed; - border-width: 1px; - border-color: var(--gray-500); - border-radius: var(--tiny-spacer); - - p { - font-size: 80%; - font-weight: 500; - } - - .purple_button { - padding: var(--tiny-spacer) var(--small-spacer); - font-size: 80%; - } -} - -.inputs_container { - margin: var(--small-spacer) 0; - - .column_container { - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; - gap: var(--large-spacer); - - @include media.tablet { - gap: var(--medium-spacer); - } - - @include media.phone { - flex-direction: column; - align-items: flex-start; - gap: var(--tiny-spacer); - } - - input { - width: 50%; - - @include media.phone { - width: 100%; - } - } - } - - .input_container { - width: 100%; - padding: var(--tiny-spacer) 0; - } - - input { - width: 100%; - padding: var(--small-spacer) var(--small-spacer); - margin: var(--tiny-spacer) 0; - border-style: solid; - border-width: 1px; - border-color: var(--gray-500); - border-radius: var(--tiny-spacer); - outline: none; - } - - input::placeholder { - color: var(--gray-500); - } - - p { - font-size: 90%; - font-weight: 500; - } - - h4 { - padding: var(--small-spacer) 0; - } -} - -.selected_tags { - display: flex; - flex-direction: row; - justify-content: flex-start; - align-content: flex-start; - flex-wrap: wrap; - overflow: scroll; - scrollbar-width: none; - gap: var(--tiny-spacer); - border: solid; - border-color: var(--gray-500); - border-width: 1px; - border-radius: var(--tiny-spacer); - padding: var(--small-spacer); - height: 160px; - - .tag_display { - align-self: flex-start; - border: solid; - border-color: var(--gray-500); - border-width: 1px; - border-radius: 3px; - padding: var(--tiny-spacer) var(--small-spacer); - font-size: 90%; - font-weight: 500; - } - - span { - color: var(--gray-500); - margin-left: var(--tiny-spacer); - cursor: pointer; - } -} - -.button_container { - display: flex; - flex-direction: row; - justify-content: right; - gap: var(--small-spacer); - - @include media.phone { - flex-direction: column; - } -} - -.white_button { - padding: var(--tiny-spacer) var(--medium-spacer); - border: none; - border-radius: var(--tiny-spacer); - cursor: pointer; - background-color: var(--background-secondary); - color: var(--purple); - font-weight: 500; - border-style: solid; - border-width: 1px; - border-color: var(--gray-300); -} - -.purple_button { - padding: var(--tiny-spacer) var(--medium-spacer); - border: none; - border-radius: var(--tiny-spacer); - cursor: pointer; - background-color: var(--purple); - color: var(--text-light); - font-weight: 500; -} - -.toggle_container { - display: flex; - align-items: center; - gap: var(--small-spacer); - - .toggle { - appearance: none; - display: inline-block; - max-width: 64px; - min-width: 64px; - position: relative; - border-radius: 50px; - outline: none; - overflow: hidden; - cursor: pointer; - height: 32px; - background-color: var(--background-secondary); - transition: background-color ease 0.3s; - } - - .toggle:before { - content: ""; - display: block; - position: absolute; - z-index: 2; - width: 28px; - height: 28px; - background: var(--gray-500); - left: 2px; - top: 2px; - border-radius: 50px; - color: var(--gray-500); - transition: all cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s; - } - - .toggle:checked { - background-color: var(--background-tertiary); - } - - .toggle:checked:before { - left: 32px; - } -} \ No newline at end of file diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx deleted file mode 100644 index 4692270..0000000 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ /dev/null @@ -1,99 +0,0 @@ -'use client'; -import styles from './ProductForm.module.scss'; -import Image from 'next/image'; -import { useState } from 'react'; -import Textbox from '@components/Textbox/Textbox'; -import { FormEvent } from 'react'; - -export default function ProductForm() { - const handleSubmit = (event: FormEvent) => { - event.preventDefault(); - console.log('Form submitted'); - }; - const [tags, setTags] = useState([]); - const addTag = (event: React.KeyboardEvent) => { - event.preventDefault(); - const input = event.target as HTMLInputElement; - const newTag = input.value; - if (newTag !== '') { - setTags((prevTags) => [...prevTags, newTag]); - } - input.value = ''; - }; - const deleteTag = (index: number) => { - setTags((prevTags) => [ - ...prevTags.slice(0, index), - ...prevTags.slice(index + 1), - ]); - }; - return ( -
-
-
- upload icon -

Drag and Drop here

-

or

- -
-
-
-

Product Name

- -
-
-

Price

-
- -
-

List Product

- -
-
-
-

Details

-
-

Tags

- ) => { - if (event.key === 'Enter') { - addTag(event); - } - }} - id="tags_search" - type="text" - placeholder="Watch.." - /> -
- {tags.map((tag, index) => ( -

- {tag} deleteTag(index)}>x -

- ))} -
-
-
-

Product Description

- -
-
-

Product Details

- -
-
-
- - -
-
-
- ); -} diff --git a/app/(pages)/(app)/products/product-form/page.tsx b/app/(pages)/(app)/products/product-form/page.tsx deleted file mode 100644 index 6c7fe41..0000000 --- a/app/(pages)/(app)/products/product-form/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import ProductForm from './_components/ProductForm'; - -export default function ViewProductForm() { - return ( -
- -
- ); -} diff --git a/app/(pages)/_components/ShortInput/ShortInput.module.scss b/app/(pages)/_components/ShortInput/ShortInput.module.scss new file mode 100644 index 0000000..46e3522 --- /dev/null +++ b/app/(pages)/_components/ShortInput/ShortInput.module.scss @@ -0,0 +1,15 @@ +.container { + position: relative; + + >input { + width: 50%; + } +} + +.label { + position: absolute; + left: 12px; + transform: translateY(-50%); + background-color: white; + padding: 0 4px; +} \ No newline at end of file diff --git a/app/(pages)/_components/ShortInput/ShortInput.tsx b/app/(pages)/_components/ShortInput/ShortInput.tsx new file mode 100644 index 0000000..9a4912c --- /dev/null +++ b/app/(pages)/_components/ShortInput/ShortInput.tsx @@ -0,0 +1,38 @@ +'use client'; +import styles from './ShortInput.module.scss'; + +interface ShortInputProps { + label: string; + value: string | number; + type: 'text' | 'number'; + updateValue?: (value: string | number) => void; + disabled?: boolean; + required?: boolean; +} + +export default function ShortInput({ + label, + value, + type, + updateValue = () => {}, + disabled, + required, +}: ShortInputProps) { + return ( +
+ + + type === 'number' + ? updateValue(Number.parseFloat(event.target.value)) + : updateValue(event.target.value) + } + disabled={disabled} + required={required} + style={{ cursor: disabled ? 'not-allowed' : 'text' }} + /> +
+ ); +} diff --git a/public/icons/trash_red.svg b/public/icons/trash_red.svg new file mode 100644 index 0000000..cb20cf3 --- /dev/null +++ b/public/icons/trash_red.svg @@ -0,0 +1 @@ + \ No newline at end of file