diff --git a/app/(marketing)/products/[productId]/_components/ProductContent.tsx b/app/(marketing)/products/[productId]/_components/ProductContent.tsx index 4c8f9e4..831d7e0 100644 --- a/app/(marketing)/products/[productId]/_components/ProductContent.tsx +++ b/app/(marketing)/products/[productId]/_components/ProductContent.tsx @@ -100,10 +100,7 @@ const ProductContent = ({ product }: Props) => { )} -
+

{product.description}

{curProductItem?.discount ? ( diff --git a/app/(store)/dashboard/[storeId]/products/_components/AvailableForm.tsx b/app/(store)/dashboard/[storeId]/products/_components/AvailableForm.tsx index 6351f9b..b8cf42b 100644 --- a/app/(store)/dashboard/[storeId]/products/_components/AvailableForm.tsx +++ b/app/(store)/dashboard/[storeId]/products/_components/AvailableForm.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState, useEffect } from "react"; +import React from "react"; import AddBtn from "./AddBtn"; import { toast } from "sonner"; import axios, { AxiosError } from "axios"; @@ -11,7 +11,6 @@ import { Available, Size } from "@prisma/client"; import { useMutation } from "@tanstack/react-query"; import SizeModal from "@/components/modal/SizeModal"; import { ProductValidator } from "@/lib/validators/product"; -import TooltipContainer from "@/components/TooltipContainer"; import { UseFormReturn, useFieldArray, Controller } from "react-hook-form"; import { Select, @@ -48,8 +47,6 @@ const AvailableForm = ({ }: Props) => { const params = useParams(); - const [mounted, setMounted] = useState(false); - const { fields, append, remove } = useFieldArray({ control: form.control, name: `productItems.${index}.availableItems`, @@ -78,32 +75,24 @@ const AvailableForm = ({ }, }); - useEffect(() => { - setMounted(true); - }, []); - - if (!mounted) return null; - return (

Add Size

- - - append({ - id: "", - sizeId: "", - price: 0, - numInStocks: 0, - }) - } - testId="add-new-size" - cypressTestId={`${testId}-add`} - disabled={disabled || isPending} - /> - + + append({ + id: "", + sizeId: "", + price: 0, + numInStocks: 0, + }) + } + testId="add-new-size" + cypressTestId={`${testId}-add`} + disabled={disabled || isPending} + />
@@ -123,9 +112,7 @@ const AvailableForm = ({ Size - - - + diff --git a/app/(store)/dashboard/[storeId]/products/_components/ProductForm.tsx b/app/(store)/dashboard/[storeId]/products/_components/ProductForm.tsx index 34b4a83..9025eb6 100644 --- a/app/(store)/dashboard/[storeId]/products/_components/ProductForm.tsx +++ b/app/(store)/dashboard/[storeId]/products/_components/ProductForm.tsx @@ -8,7 +8,6 @@ import axios, { AxiosError } from "axios"; import AvailableForm from "./AvailableForm"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; -import TextEditor from "@/components/TextEditor"; import BtnSpinner from "@/components/BtnSpinner"; import ImageUpload from "@/components/ImageUpload"; import MultiSelect from "@/components/MultiSelect"; @@ -16,7 +15,6 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useParams, useRouter } from "next/navigation"; import ColorModal from "@/components/modal/ColorModal"; import AlertModal from "@/components/modal/AlertModal"; -import TooltipContainer from "@/components/TooltipContainer"; import CategoryModal from "@/components/modal/CategoryModal"; import { useMutation, useQuery } from "@tanstack/react-query"; import { useForm, useFieldArray, Controller } from "react-hook-form"; @@ -44,6 +42,7 @@ import { FormItem, FormMessage, } from "@/components/ui/form"; +import { Textarea } from "@/components/ui/textarea"; type ProductItemType = ProductItem & { availableItems: Available[]; @@ -228,7 +227,7 @@ const ProductForm = ({ data }: Props) => { }; return ( -
+ <> setOpen(false)} @@ -237,138 +236,138 @@ const ProductForm = ({ data }: Props) => { featureToDelete="product" /> -
- -
-
- setHoneyPot(e.target.value)} - /> -
+
+ + +
+
+ setHoneyPot(e.target.value)} + /> +
-
- ( - - Name +
+ ( + + Name - - - + + + - - - )} - /> + + + )} + /> - ( - - - Category + ( + + + Category - - + - - - + + + + + + + + + + )} + /> +
+ + ( + + Description - + placeholder="Product Description..." + data-cy="product-description-input" + rows={10} + /> - + )} />
- ( - - Description - - - - - - - - )} - /> -
- -
+
- {form.formState.errors.productItems && ( -
- {form.formState.errors.productItems.message} -
- )} + {form.formState.errors.productItems && ( +
+ {form.formState.errors.productItems.message} +
+ )} -
-

Add Product Details

+
+

Add Product Details

- - -
- -
- {fields.map((item, index) => ( -
- ( - - Images (Max 6) - - - - - - - - )} - /> - - - -
- ( - - - Colors - - - - - - - - - - {!colorsError && - !colorsLoading && - colors && - colors.length > 0 && ( - ({ - value: color.id, - label: color.name, - }))} - value={field.value} - onChange={field.onChange} - placeholder="Choose Colors..." - testId={`product-item-form-${index}-color`} - /> - )} - - - - - )} - /> +
+
+ {fields.map((item, index) => ( +
( - Discount (%) + Images (Max 6) - @@ -497,80 +418,156 @@ const ProductForm = ({ data }: Props) => { )} /> -
-
- {data?.productItems?.[index]?.id ? ( - - ) : ( - - )} -
-
- ))} -
+ -
- {data && ( - - )} +
+ ( + + + Colors -
- + + + + + + + {!colorsError && + !colorsLoading && + colors && + colors.length > 0 && ( + ({ + value: color.id, + label: color.name, + }))} + value={field.value} + onChange={field.onChange} + placeholder="Choose Colors..." + testId={`product-item-form-${index}-color`} + /> + )} + + + + + )} + /> + ( + + Discount (%) + + + + + + + + )} + /> +
+ +
+ {data?.productItems?.[index]?.id ? ( + + ) : ( + + )} +
+
+ ))} +
+ +
{data && ( )} + +
+ + + {data && ( + + )} +
-
- - -
+ + +
+ ); }; diff --git a/app/api/stores/[storeId]/products/[productId]/route.ts b/app/api/stores/[storeId]/products/[productId]/route.ts index 12a9faf..ba81674 100644 --- a/app/api/stores/[storeId]/products/[productId]/route.ts +++ b/app/api/stores/[storeId]/products/[productId]/route.ts @@ -4,10 +4,10 @@ import { NextResponse } from "next/server"; import { getCurrentPrice } from "@/lib/utils"; import { checkText } from "@/actions/checkText"; import { checkImage } from "@/actions/checkImage"; -import { sendDeletedProductEmail, sendUpdatedProductEmail } from "@/lib/mail"; import { currentRole, currentUser } from "@/lib/auth"; import { UserRole, storeStatus } from "@prisma/client"; import { ProductSchema } from "@/lib/validators/product"; +import { sendDeletedProductEmail, sendUpdatedProductEmail } from "@/lib/mail"; export async function PATCH( request: Request, diff --git a/components/TextEditor.tsx b/components/TextEditor.tsx deleted file mode 100644 index da7a22a..0000000 --- a/components/TextEditor.tsx +++ /dev/null @@ -1,37 +0,0 @@ -"use client"; - -import React, { useState, useEffect } from "react"; -import ReactQuill from "react-quill"; -import "react-quill/dist/quill.snow.css"; - -type Props = { - value: string | undefined; - onChange: (value: string) => void; - disabled: boolean; -}; - -const TextEditor = ({ value, onChange, disabled }: Props) => { - const [isClient, setIsClient] = useState(false); - - useEffect(() => { - setIsClient(typeof window !== "undefined"); - }, []); - - if (!isClient) { - return null; - } - - return ( -
- onChange(content)} - readOnly={disabled} - /> -
- ); -}; - -export default TextEditor; diff --git a/cypress/e2e/product.cy.ts b/cypress/e2e/product.cy.ts index e6c1e4e..9f22e22 100644 --- a/cypress/e2e/product.cy.ts +++ b/cypress/e2e/product.cy.ts @@ -51,7 +51,9 @@ describe("Product for store", () => { .type("Test product"); //Product Description - cy.get(".ql-editor").should("be.visible").type("Test product description"); + cy.get('[data-cy="product-description-input"]') + .should("exist") + .type("Test product description"); //Category cy.get('[data-cy="product-category-select-trigger"]') @@ -212,7 +214,7 @@ describe("Product for store", () => { .type("Test product update"); //Product Description - cy.get(".ql-editor") + cy.get('[data-cy="product-description-input"]') .should("exist") .clear() .type("Test product description update"); diff --git a/package-lock.json b/package-lock.json index e7ab28a..bd72a9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,6 @@ "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.3", "react-icons": "^5.0.1", - "react-quill": "^2.0.0", "react-responsive-carousel": "^3.2.23", "react-spinners": "^0.13.8", "recharts": "^2.12.1", @@ -5936,14 +5935,6 @@ "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", "devOptional": true }, - "node_modules/@types/quill": { - "version": "1.3.10", - "resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz", - "integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==", - "dependencies": { - "parchment": "^1.1.2" - } - }, "node_modules/@types/react": { "version": "18.2.48", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.48.tgz", @@ -7330,14 +7321,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "engines": { - "node": ">=0.8" - } - }, "node_modules/clsx": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", @@ -8167,25 +8150,6 @@ } } }, - "node_modules/deep-equal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", - "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", - "dependencies": { - "is-arguments": "^1.1.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.5.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -8217,6 +8181,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -9142,11 +9107,6 @@ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==" }, - "node_modules/eventemitter3": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==" - }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -9264,11 +9224,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz", - "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==" - }, "node_modules/fast-equals": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz", @@ -9689,6 +9644,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9999,6 +9955,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, "dependencies": { "has-symbols": "^1.0.2" }, @@ -10286,6 +10243,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -10409,6 +10367,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -10559,6 +10518,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -12646,6 +12606,7 @@ "version": "1.1.5", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.1.3" @@ -12661,6 +12622,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "engines": { "node": ">= 0.4" } @@ -12853,11 +12815,6 @@ "node": ">=6" } }, - "node_modules/parchment": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz", - "integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -13449,32 +13406,6 @@ } ] }, - "node_modules/quill": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz", - "integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==", - "dependencies": { - "clone": "^2.1.1", - "deep-equal": "^1.0.1", - "eventemitter3": "^2.0.3", - "extend": "^3.0.2", - "parchment": "^1.1.4", - "quill-delta": "^3.6.2" - } - }, - "node_modules/quill-delta": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz", - "integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==", - "dependencies": { - "deep-equal": "^1.0.1", - "extend": "^3.0.2", - "fast-diff": "1.1.2" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -13571,20 +13502,6 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, - "node_modules/react-quill": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz", - "integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==", - "dependencies": { - "@types/quill": "^1.3.10", - "lodash": "^4.17.4", - "quill": "^1.3.7" - }, - "peerDependencies": { - "react": "^16 || ^17 || ^18", - "react-dom": "^16 || ^17 || ^18" - } - }, "node_modules/react-remove-scroll": { "version": "2.5.5", "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz", @@ -13804,6 +13721,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dev": true, "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -14150,6 +14068,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dev": true, "dependencies": { "define-data-property": "^1.0.1", "functions-have-names": "^1.2.3", diff --git a/package.json b/package.json index 530a6bd..50d5026 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.3", "react-icons": "^5.0.1", - "react-quill": "^2.0.0", "react-responsive-carousel": "^3.2.23", "react-spinners": "^0.13.8", "recharts": "^2.12.1",