From 7e0847374298b30e418c1d6575f1297cf16358e7 Mon Sep 17 00:00:00 2001 From: palina0k Date: Mon, 7 Apr 2025 20:18:01 -0700 Subject: [PATCH 1/8] Initial Commit to Create Product Listing Page (currently under ProductForm) --- .../_components/ProductForm.module.scss | 16 ++- .../product-form/_components/ProductForm.tsx | 125 +++++++++--------- 2 files changed, 80 insertions(+), 61 deletions(-) diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss index dbba5eb..7e5b1c3 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss @@ -1,9 +1,15 @@ @use 'media'; -.container { +.container{ + display: flex; + flex-direction: column; +} + +.listing { width: 60%; display: flex; flex-direction: column; + margin: auto; justify-content: center; padding: var(--medium-spacer); text-align: left; @@ -15,6 +21,14 @@ border-color: var(--gray-100); } +.title { + width: 60%; + justify-content: center; + margin: auto; + padding: var(--small-spacer); + text-align: left; +} + .img_container { padding: var(--large-spacer) var(--medium-spacer); margin-bottom: var(--medium-spacer); diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index 92c7dc4..db933e9 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -28,72 +28,77 @@ export default function ProductForm() { }; return (
-
-
- upload icon -

Drag and Drop here

-

or

- -
-
-
-

Product Name

- +
+

Listing

+
+
+ +
+ upload icon +

Drag and Drop here

+

or

+
-
-

Price

-
- -
-

List Product

- +
+
+

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 -

- ))} +

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

+
-
-

Product Description

- -
-
-

Product Details

- +
+ +
-
-
- - -
- + +
); } From 3c49952a37b12920b677343227cd332611637418 Mon Sep 17 00:00:00 2001 From: palina0k Date: Mon, 14 Apr 2025 20:54:18 -0700 Subject: [PATCH 2/8] Created a nav bar to separate about, details, carriers sub-pages. Still working on rendering each sub-page. --- .../_components/ProductForm.module.scss | 84 ++++++++++++++-- .../product-form/_components/ProductForm.tsx | 95 ++++++++++++++++++- 2 files changed, 169 insertions(+), 10 deletions(-) diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss index 7e5b1c3..279f0f7 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss @@ -5,26 +5,89 @@ 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(--medium-spacer); + padding: var(--small-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); + 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; + //margin: auto; padding: var(--small-spacer); text-align: left; } @@ -181,6 +244,15 @@ 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; diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index db933e9..06c38ea 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -5,7 +5,38 @@ import React, { useState } from 'react'; import Textbox from '@components/Textbox/Textbox'; import { FormEvent } from 'react'; +const ItemsBar = ({ + items, + activeIndex, + onTabChange, +}: { + items: string[]; + activeIndex: number; + onTabChange: (index: number) => void; +}) => { + return ( + + ); +}; + export default function ProductForm() { + const [activeTab, setActiveTab] = useState(0); const handleSubmit = (event: FormEvent) => { event.preventDefault(); console.log('Form submitted'); @@ -26,12 +57,60 @@ export default function ProductForm() { ...prevTags.slice(index + 1), ]); }; + const renderContent = () => { + switch (activeTab) { + case 0: + return ( +
+

About the Product

+

details

+
+ ); + case 1: + return ( +
+

Details

+

details

+
+ ); + case 2: + return ( +
+

Shipping Information

+

placeholder

+
+ ); + case 3: + return ( +
+

Carriers Information

+

placeholder

+
+ ); + default: + return null; + } + }; return (
-
-

Listing

+
+
+

Listing

+
+
+ +
+ {/* Content of Product Form */}
+ {/* Navigation Bar == Items bar*/} + + {/* Dynamic Content */} +
{renderContent()}
- - + +
From 88f3d927a9374abfbe222d3bea222ba4b01cedbd Mon Sep 17 00:00:00 2001 From: palina0k Date: Thu, 24 Apr 2025 19:31:13 -0700 Subject: [PATCH 3/8] About and Details contain all of the necessary inputs now, only missing correct design. --- .../_components/ProductForm.module.scss | 212 +++++++-------- .../product-form/_components/ProductForm.tsx | 254 +++++++++++++----- 2 files changed, 289 insertions(+), 177 deletions(-) diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss index 279f0f7..12908eb 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss @@ -92,121 +92,123 @@ text-align: left; } -.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 { +.subpage_container{ + .img_container { + padding: var(--large-spacer) var(--medium-spacer); + margin-bottom: var(--medium-spacer); display: flex; - flex-direction: row; - justify-content: flex-start; + flex-direction: column; + justify-content: center; 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; + 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); - outline: none; - } - - input::placeholder { - color: var(--gray-500); - } - - p { - font-size: 90%; - font-weight: 500; + + p { + font-size: 80%; + font-weight: 500; + } + + .purple_button { + padding: var(--tiny-spacer) var(--small-spacer); + font-size: 80%; + } } - - h4 { - padding: var(--small-spacer) 0; + + .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; + + .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: 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; + 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; + } } } diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index 06c38ea..69e4b22 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -2,7 +2,6 @@ import styles from './ProductForm.module.scss'; import Image from 'next/image'; import React, { useState } from 'react'; -import Textbox from '@components/Textbox/Textbox'; import { FormEvent } from 'react'; const ItemsBar = ({ @@ -57,34 +56,205 @@ export default function ProductForm() { ...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) => { + const { name, value } = event.target; + setFormData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; const renderContent = () => { switch (activeTab) { case 0: return ( -
-

About the Product

-

details

+
+ {/* Title - Text Box, Category - Text Box + Description - Larger Text Box + Product Type - Dropdown selector, Tags - Dropdown selector + Media - Image Uploading (placholder) */} +
+
+
+

Title

+ +

Category

+
+ + {/*
+

List Product

+ +
*/} +
+
+
+

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

+ +
+
+
); case 1: return ( -
-

Details

-

details

+
+
+ {/* 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

+
+ +
+
+
); case 2: return ( -
+

Shipping Information

-

placeholder

+

Placeholder

); case 3: return ( -
+

Carriers Information

-

placeholder

+

Placeholder

); default: @@ -110,68 +280,8 @@ export default function ProductForm() { onTabChange={setActiveTab} /> {/* Dynamic Content */} -
{renderContent()}
-
- 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

- -
-
+
{renderContent()}
Date: Thu, 24 Apr 2025 19:49:08 -0700 Subject: [PATCH 4/8] Fixed Errors for TypeScript check --- .../(app)/products/product-form/_components/ProductForm.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index 69e4b22..3d5846d 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -76,7 +76,7 @@ export default function ProductForm() { title: '', description: '', }); - const handleInputChange = (event) => { + const handleInputChange = (event: React.ChangeEvent) => { const { name, value } = event.target; setFormData((prevData) => ({ ...prevData, @@ -99,7 +99,7 @@ export default function ProductForm() {

Category

@@ -120,7 +120,7 @@ export default function ProductForm() {
From 7388761aded13ffbff4085e5475668367e24285e Mon Sep 17 00:00:00 2001 From: palina0k Date: Thu, 22 May 2025 22:10:54 -0700 Subject: [PATCH 5/8] Work in Progress - separated each component of the listing page into its own file; incorporated the existing Textbox component; still working on the accurate design/format as well as how the listing will be saved/stored. --- .../product-form/_components/AboutPage.tsx | 135 +++++++++++ .../product-form/_components/CarriersPage.tsx | 11 + .../product-form/_components/DetailsPage.tsx | 78 ++++++ .../_components/ProductForm.module.scss | 43 ++-- .../product-form/_components/ProductForm.tsx | 225 ++---------------- .../product-form/_components/ShippingPage.tsx | 11 + .../ShortInput/ShortInput.module.scss | 15 ++ .../_components/ShortInput/ShortInput.tsx | 38 +++ public/icons/trash_red.svg | 1 + 9 files changed, 328 insertions(+), 229 deletions(-) create mode 100644 app/(pages)/(app)/products/product-form/_components/AboutPage.tsx create mode 100644 app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx create mode 100644 app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx create mode 100644 app/(pages)/(app)/products/product-form/_components/ShippingPage.tsx create mode 100644 app/(pages)/_components/ShortInput/ShortInput.module.scss create mode 100644 app/(pages)/_components/ShortInput/ShortInput.tsx create mode 100644 public/icons/trash_red.svg diff --git a/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx b/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx new file mode 100644 index 0000000..67efda7 --- /dev/null +++ b/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx @@ -0,0 +1,135 @@ +'use client'; +import styles from './ProductForm.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/product-form/_components/CarriersPage.tsx b/app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx new file mode 100644 index 0000000..f7d51e2 --- /dev/null +++ b/app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx @@ -0,0 +1,11 @@ +'use client'; +import styles from './ProductForm.module.scss'; + +export default function CarriersPage() { + return ( +
+

Carriers Information

+

Placeholder

+
+ ); +} diff --git a/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx b/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx new file mode 100644 index 0000000..17ceec1 --- /dev/null +++ b/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx @@ -0,0 +1,78 @@ +'use client'; +import styles from './ProductForm.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/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss index 12908eb..c39dc52 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss @@ -119,33 +119,39 @@ } .inputs_container { - margin: var(--small-spacer) 0; - + + .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: row; - justify-content: flex-start; - align-items: center; - gap: var(--large-spacer); - - @include media.tablet { - gap: var(--medium-spacer); - } - + flex-direction: column; + gap: var(--tiny-spacer); + @include media.phone { - flex-direction: column; - align-items: flex-start; gap: var(--tiny-spacer); - } - + } + input { - width: 50%; - + width: 100%; + @include media.phone { - width: 100%; + width: 100%; } } } + .input_container { width: 100%; @@ -216,6 +222,7 @@ display: flex; flex-direction: row; justify-content: right; + align-items: center; gap: var(--small-spacer); @include media.phone { diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index 3d5846d..d417b71 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -3,6 +3,10 @@ import styles from './ProductForm.module.scss'; import Image from 'next/image'; 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, @@ -40,223 +44,16 @@ export default function ProductForm() { 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), - ]); - }; - 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, - })); - }; const renderContent = () => { switch (activeTab) { case 0: - return ( -
- {/* Title - Text Box, Category - Text Box - Description - Larger Text Box - Product Type - Dropdown selector, Tags - Dropdown selector - Media - Image Uploading (placholder) */} - -
-
-

Title

- -

Category

-
- - {/*
-

List Product

- -
*/} -
-
-
-

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

- -
-
- -
- ); + return ; case 1: - 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

-
- -
-
-
-
- ); + return ; case 2: - return ( -
-

Shipping Information

-

Placeholder

-
- ); + return ; case 3: - return ( -
-

Carriers Information

-

Placeholder

-
- ); + return ; default: return null; } @@ -268,6 +65,12 @@ export default function ProductForm() {

Listing

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

Shipping Information

+

Placeholder

+
+ ); +} 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..bac3a81 --- /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: any) => 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 From 3902580d7510a0fc9ed357765de861544aa4ebe0 Mon Sep 17 00:00:00 2001 From: palina0k Date: Fri, 23 May 2025 09:22:15 -0700 Subject: [PATCH 6/8] Two minor fixes that caused tests to fail. --- .../(app)/products/product-form/_components/ProductForm.tsx | 1 - app/(pages)/_components/ShortInput/ShortInput.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx index 545617e..d417b71 100644 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx @@ -2,7 +2,6 @@ import styles from './ProductForm.module.scss'; import Image from 'next/image'; import React, { useState } from 'react'; -import Textbox from '@components/Textbox/Textbox'; import { FormEvent } from 'react'; import AboutPage from './AboutPage'; import DetailsPage from './DetailsPage'; diff --git a/app/(pages)/_components/ShortInput/ShortInput.tsx b/app/(pages)/_components/ShortInput/ShortInput.tsx index bac3a81..9a4912c 100644 --- a/app/(pages)/_components/ShortInput/ShortInput.tsx +++ b/app/(pages)/_components/ShortInput/ShortInput.tsx @@ -5,7 +5,7 @@ interface ShortInputProps { label: string; value: string | number; type: 'text' | 'number'; - updateValue?: (value: any) => void; + updateValue?: (value: string | number) => void; disabled?: boolean; required?: boolean; } From da7156b5e138870b9ef0f47a2ec7a33cab71f433 Mon Sep 17 00:00:00 2001 From: brandonw504 Date: Thu, 26 Jun 2025 21:47:37 -0700 Subject: [PATCH 7/8] Some renaming --- .../product-form/_components/AboutPage.tsx | 135 -------- .../product-form/_components/CarriersPage.tsx | 11 - .../product-form/_components/DetailsPage.tsx | 78 ----- .../_components/ProductForm.module.scss | 307 ------------------ .../product-form/_components/ProductForm.tsx | 104 ------ .../product-form/_components/ShippingPage.tsx | 11 - .../(app)/products/product-form/page.tsx | 9 - 7 files changed, 655 deletions(-) delete mode 100644 app/(pages)/(app)/products/product-form/_components/AboutPage.tsx delete mode 100644 app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx delete mode 100644 app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx delete mode 100644 app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss delete mode 100644 app/(pages)/(app)/products/product-form/_components/ProductForm.tsx delete mode 100644 app/(pages)/(app)/products/product-form/_components/ShippingPage.tsx delete mode 100644 app/(pages)/(app)/products/product-form/page.tsx diff --git a/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx b/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx deleted file mode 100644 index 67efda7..0000000 --- a/app/(pages)/(app)/products/product-form/_components/AboutPage.tsx +++ /dev/null @@ -1,135 +0,0 @@ -'use client'; -import styles from './ProductForm.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/product-form/_components/CarriersPage.tsx b/app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx deleted file mode 100644 index f7d51e2..0000000 --- a/app/(pages)/(app)/products/product-form/_components/CarriersPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; -import styles from './ProductForm.module.scss'; - -export default function CarriersPage() { - return ( -
-

Carriers Information

-

Placeholder

-
- ); -} diff --git a/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx b/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx deleted file mode 100644 index 17ceec1..0000000 --- a/app/(pages)/(app)/products/product-form/_components/DetailsPage.tsx +++ /dev/null @@ -1,78 +0,0 @@ -'use client'; -import styles from './ProductForm.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/product-form/_components/ProductForm.module.scss b/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss deleted file mode 100644 index c39dc52..0000000 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.module.scss +++ /dev/null @@ -1,307 +0,0 @@ -@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/product-form/_components/ProductForm.tsx b/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx deleted file mode 100644 index d417b71..0000000 --- a/app/(pages)/(app)/products/product-form/_components/ProductForm.tsx +++ /dev/null @@ -1,104 +0,0 @@ -'use client'; -import styles from './ProductForm.module.scss'; -import Image from 'next/image'; -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 ProductForm() { - 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 ( -
-
-
-

Listing

-
-
- delete icon - -
-
- {/* Content of Product Form */} -
- {/* Navigation Bar == Items bar*/} - - {/* Dynamic Content */} -
-
{renderContent()}
-
- - -
-
-
-
- ); -} diff --git a/app/(pages)/(app)/products/product-form/_components/ShippingPage.tsx b/app/(pages)/(app)/products/product-form/_components/ShippingPage.tsx deleted file mode 100644 index 9c86823..0000000 --- a/app/(pages)/(app)/products/product-form/_components/ShippingPage.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client'; -import styles from './ProductForm.module.scss'; - -export default function ShippingPagge() { - return ( -
-

Shipping Information

-

Placeholder

-
- ); -} 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 ( -
- -
- ); -} From 7afb7ada786ce05fab0dfc185e935f3bf613e8d8 Mon Sep 17 00:00:00 2001 From: brandonw504 Date: Thu, 26 Jun 2025 23:45:37 -0700 Subject: [PATCH 8/8] Renamed to create --- .../products/create/_components/AboutPage.tsx | 135 ++++++++ .../create/_components/CarriersPage.tsx | 11 + .../_components/CreateProductForm.module.scss | 307 ++++++++++++++++++ .../create/_components/CreateProductForm.tsx | 97 ++++++ .../create/_components/DetailsPage.tsx | 78 +++++ .../create/_components/ShippingPage.tsx | 11 + app/(pages)/(app)/products/create/page.tsx | 9 + 7 files changed, 648 insertions(+) create mode 100644 app/(pages)/(app)/products/create/_components/AboutPage.tsx create mode 100644 app/(pages)/(app)/products/create/_components/CarriersPage.tsx create mode 100644 app/(pages)/(app)/products/create/_components/CreateProductForm.module.scss create mode 100644 app/(pages)/(app)/products/create/_components/CreateProductForm.tsx create mode 100644 app/(pages)/(app)/products/create/_components/DetailsPage.tsx create mode 100644 app/(pages)/(app)/products/create/_components/ShippingPage.tsx create mode 100644 app/(pages)/(app)/products/create/page.tsx 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 ( +
+ +
+ ); +}