From d3f358d7c587f6536c57fd3d5c51d6e2b6618224 Mon Sep 17 00:00:00 2001 From: Joshua Ogbonna Date: Mon, 25 Nov 2024 10:09:25 +0100 Subject: [PATCH] chore: work on responsiveness for studio --- src/app/congratulations/page.tsx | 2 +- src/app/create-rare-item/page.tsx | 1120 +++++++++++++------------ src/app/page.tsx | 789 +++++++++-------- src/components/footer.js | 269 ++++-- src/components/ui/navbar.tsx | 540 ++++++------ src/components/ui/navigation-menu.tsx | 204 ++--- 6 files changed, 1638 insertions(+), 1286 deletions(-) diff --git a/src/app/congratulations/page.tsx b/src/app/congratulations/page.tsx index 94959bd..a3cf3f7 100644 --- a/src/app/congratulations/page.tsx +++ b/src/app/congratulations/page.tsx @@ -48,7 +48,7 @@ export default function Congratulations() { ) : selectedOption === "rare" ? ( - + diff --git a/src/app/create-rare-item/page.tsx b/src/app/create-rare-item/page.tsx index c22829b..a1e4733 100644 --- a/src/app/create-rare-item/page.tsx +++ b/src/app/create-rare-item/page.tsx @@ -1,317 +1,312 @@ -'use client' -import React, { useState, useRef, ChangeEvent } from 'react' +"use client"; +import React, { useState, useRef, ChangeEvent } from "react"; import { - Button, - Checkbox, - Input, - Label, - Navbar, - PreviewIcon, - Textarea, - UploadIcon, - Form, - FormControl, - FormDescription, - FormField, - FormItem, - FormLabel, - FormMessage, -} from '@/components' + Button, + Checkbox, + Input, + Label, + Navbar, + PreviewIcon, + Textarea, + UploadIcon, + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components"; // import { UploadButton } from '@/utils/uploadthing' -import { zodResolver } from '@hookform/resolvers/zod' -import { useForm } from 'react-hook-form' -import { z } from 'zod' -import Image from 'next/image' -import { toast, ToastContainer } from 'react-toastify' -import { useRouter } from 'next/navigation' -import { NFTStorage } from 'nft.storage' -import { v4 as uuidv4 } from 'uuid'; -const API_KEY = process.env.NEXT_PUBLIC_STORAGE_API! -const client = new NFTStorage({ token: API_KEY }) +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; +import Image from "next/image"; +import { toast, ToastContainer } from "react-toastify"; +import { useRouter } from "next/navigation"; +import { NFTStorage } from "nft.storage"; +import { v4 as uuidv4 } from "uuid"; +const API_KEY = process.env.NEXT_PUBLIC_STORAGE_API!; +const client = new NFTStorage({ token: API_KEY }); const formSchema = z.object({ - name: z.string().min(2, { - message: 'Phygital name must be at least 2 characters', - }).regex(/^[a-zA-Z0-9\s]*$/, { - message: 'Phygital name must only contain letters and numbers', - }), - category: z - .array(z.string()), - // .refine((value) => value.some((item) => item), { - // message: 'You have to select at least one category.', - // }), + name: z + .string() + .min(2, { + message: "Phygital name must be at least 2 characters", + }) + .regex(/^[a-zA-Z0-9\s]*$/, { + message: "Phygital name must only contain letters and numbers", + }), + category: z.array(z.string()), + // .refine((value) => value.some((item) => item), { + // message: 'You have to select at least one category.', + // }), - description: z - .string() - .min(2, { message: 'Description must be at least 2 characters' }) - .max(1000, { - message: 'Phygital description should be less than 1000 words', - }), - price: z.string().min(1, { message: 'Price must be provided' }), - quantity: z.string().min(1, { message: 'Quantity must be provided' }), - royality: z.string(), - product_info: z - .string() - .min(2, { message: 'Product Information must be at least 2 characters' }), - image: z.string(), - brand_name: z.string(), - tags: z.array(z.string()).optional(), -}) + description: z + .string() + .min(2, { message: "Description must be at least 2 characters" }) + .max(1000, { + message: "Phygital description should be less than 1000 words", + }), + price: z.string().min(1, { message: "Price must be provided" }), + quantity: z.string().min(1, { message: "Quantity must be provided" }), + royality: z.string(), + product_info: z + .string() + .min(2, { message: "Product Information must be at least 2 characters" }), + image: z.string(), + brand_name: z.string(), + tags: z.array(z.string()).optional(), +}); const items = [ - { - id: 'fashion', - label: 'Fashion', - }, - { - id: 'home & decor', - label: 'Home & Decor', - }, - { - id: 'sustainable goods', - label: 'Sustainable goods', - }, - { - id: 'collectibles', - label: 'Collectibles', - }, - { - id: 'functional items', - label: 'Functional items', - }, - { - id: 'tech enabled', - label: 'Tech enabled', - }, - { - id: 'art & photography', - label: 'Art & Photography', - }, - { - id: 'luxury goods', - label: 'Luxury goods', - }, - { - id: 'music lovers', - label: 'Music lovers', - }, -] + { + id: "fashion", + label: "Fashion", + }, + { + id: "home & decor", + label: "Home & Decor", + }, + { + id: "sustainable goods", + label: "Sustainable goods", + }, + { + id: "collectibles", + label: "Collectibles", + }, + { + id: "functional items", + label: "Functional items", + }, + { + id: "tech enabled", + label: "Tech enabled", + }, + { + id: "art & photography", + label: "Art & Photography", + }, + { + id: "luxury goods", + label: "Luxury goods", + }, + { + id: "music lovers", + label: "Music lovers", + }, +]; interface TagsInputProps { - selectedTags: (tags: string[]) => void; - tags: string[]; - } - - const TagsInput: React.FC = ({ selectedTags, tags }) => { - const [tagList, setTagList] = useState(tags); - - const removeTags = (indexToRemove: number) => { - const updatedTags = tagList.filter((_, index) => index !== indexToRemove); - setTagList(updatedTags); - selectedTags(updatedTags); - }; - - const addTags = (event: React.KeyboardEvent) => { - if (event.key === "Enter") { - event.preventDefault(); // Prevent default action for Enter key - const inputValue = (event.target as HTMLInputElement).value.trim(); - if (inputValue !== "" && !tagList.includes(inputValue)) { - const updatedTags = [...tagList, inputValue]; - setTagList(updatedTags); - selectedTags(updatedTags); - (event.target as HTMLInputElement).value = ""; // Clear input - } - } - }; - - return ( -
-
    - {tagList.map((tag, index) => ( -
  • - {tag} - removeTags(index)} - > - x - -
  • - ))} -
- -
- ); - }; + selectedTags: (tags: string[]) => void; + tags: string[]; +} -export default function CreateRareItem() { +const TagsInput: React.FC = ({ selectedTags, tags }) => { + const [tagList, setTagList] = useState(tags); - const apiUrl = process.env.NEXT_PUBLIC_URI; + const removeTags = (indexToRemove: number) => { + const updatedTags = tagList.filter((_, index) => index !== indexToRemove); + setTagList(updatedTags); + selectedTags(updatedTags); + }; - const [showForm, setShowForm] = useState(false) - const [productURL, setProductURL] = useState('') - const [tags, setTags] = useState([]) + const addTags = (event: React.KeyboardEvent) => { + if (event.key === "Enter") { + event.preventDefault(); // Prevent default action for Enter key + const inputValue = (event.target as HTMLInputElement).value.trim(); + if (inputValue !== "" && !tagList.includes(inputValue)) { + const updatedTags = [...tagList, inputValue]; + setTagList(updatedTags); + selectedTags(updatedTags); + (event.target as HTMLInputElement).value = ""; // Clear input + } + } + }; - const handleSubmit = () => { - if (!productURL) { - toast.warning('Product URL is required.') - return - } else { - localStorage.setItem("producturl", productURL) - } - } + return ( +
+
    + {tagList.map((tag, index) => ( +
  • + {tag} + removeTags(index)} + > + x + +
  • + ))} +
+ +
+ ); +}; +export default function CreateRareItem() { + const apiUrl = process.env.NEXT_PUBLIC_URI; - const handleCheckboxChange = () => { - setShowForm(!showForm); - }; + const [showForm, setShowForm] = useState(false); + const [productURL, setProductURL] = useState(""); + const [tags, setTags] = useState([]); - const [file, setFile] = useState(null); - const [cid, setCid] = useState(""); - const [cidCover, setCidCover] = useState(""); - const [uploading, setUploading] = useState(false); + const handleSubmit = () => { + if (!productURL) { + toast.warning("Product URL is required."); + return; + } else { + localStorage.setItem("producturl", productURL); + } + }; - const inputFile = useRef(null); - const uploadFile = async (fileToUpload: string | Blob) => { - try { - setUploading(true); - const data = new FormData(); - data.set("file", fileToUpload); - const res = await fetch("/api/files", { - method: "POST", - body: data, - }); - const resData = await res.json(); - setCid(resData.IpfsHash); - toast.success('Upload Completed!', { - position: 'top-left', - }) - console.log(resData.IpfsHash); - setUploading(false); - } catch (e) { - console.log(e); - setUploading(false); - alert("Trouble uploading file"); - } - }; + const handleCheckboxChange = () => { + setShowForm(!showForm); + }; - const router = useRouter() - const [imageUrl, setImageUrl] = useState('') - const [preview, setPreview] = useState(false) - const [loading, setLoading] = useState(false) - const [imageError, setImageError] = useState(false) + const [file, setFile] = useState(null); + const [cid, setCid] = useState(""); + const [cidCover, setCidCover] = useState(""); + const [uploading, setUploading] = useState(false); - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - name: '', - category: [], - description: '', - price: '', - quantity: '', - royality: '', - product_info: '', - image: '', - brand_name: '', - tags: [], - }, - }) + const inputFile = useRef(null); + const uploadFile = async (fileToUpload: string | Blob) => { + try { + setUploading(true); + const data = new FormData(); + data.set("file", fileToUpload); + const res = await fetch("/api/files", { + method: "POST", + body: data, + }); + const resData = await res.json(); + setCid(resData.IpfsHash); + toast.success("Upload Completed!", { + position: "top-left", + }); + console.log(resData.IpfsHash); + setUploading(false); + } catch (e) { + console.log(e); + setUploading(false); + alert("Trouble uploading file"); + } + }; - async function onSubmit(values: z.infer) { - if (!cid) { - setImageError(true) - } + const router = useRouter(); + const [imageUrl, setImageUrl] = useState(""); + const [preview, setPreview] = useState(false); + const [loading, setLoading] = useState(false); + const [imageError, setImageError] = useState(false); - try { - if (typeof window !== 'undefined' && localStorage) { - const brand_name = localStorage.getItem('brand_name') - values.image = "ipfs://" + cid - values.brand_name = brand_name! - values.tags = tags - localStorage.setItem('phygitalData', JSON.stringify(values)) + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + name: "", + category: [], + description: "", + price: "", + quantity: "", + royality: "", + product_info: "", + image: "", + brand_name: "", + tags: [], + }, + }); - if (cid !== '') { - setLoading(true) - // const phygitalId = uuidv4() - // const CollectionId = localStorage.getItem("CollectionId") - // const walletAddress = localStorage.getItem("walletAddress") - // const productUrl = localStorage.getItem("producturl") - // const response = await fetch(`${apiUrl}/phygitals`, { - // method: 'POST', - // headers: { - // 'Content-Type': 'application/json', - // }, - // body: JSON.stringify({ - // id: phygitalId, - // collection_id: CollectionId, - // deployer_address: walletAddress, - // product_url: productUrl, - // name: values.name, - // brand_name: values.brand_name, - // category: { data: values.category }, - // description: values.description, - // price: parseFloat(values.price), - // quantity: parseInt(values.quantity), - // royality: parseInt(values.royality), - // product_info: values.product_info, - // image: values.image, - // }), - // }) - // const phygital = await response.json(); - // localStorage.setItem("PhygitalId", phygital.id); - router.push( - `/create-phygital-detail` - ) - } - } else if (!imageError && cid === '') { - toast.warning('Wait for your image to finish upload') - } - } catch (error) { - console.log('Errors' + error) - toast.warning('Failed to create Collection') - setLoading(false) - } - } + async function onSubmit(values: z.infer) { + if (!cid) { + setImageError(true); + } + try { + if (typeof window !== "undefined" && localStorage) { + const brand_name = localStorage.getItem("brand_name"); + values.image = "ipfs://" + cid; + values.brand_name = brand_name!; + values.tags = tags; + localStorage.setItem("phygitalData", JSON.stringify(values)); - const uploadImage = (e: ChangeEvent) => { - const files = e.target.files; - if (files && files.length > 0) { - setFile(files[0]); - uploadFile(files[0]); + if (cid !== "") { + setLoading(true); + // const phygitalId = uuidv4() + // const CollectionId = localStorage.getItem("CollectionId") + // const walletAddress = localStorage.getItem("walletAddress") + // const productUrl = localStorage.getItem("producturl") + // const response = await fetch(`${apiUrl}/phygitals`, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json', + // }, + // body: JSON.stringify({ + // id: phygitalId, + // collection_id: CollectionId, + // deployer_address: walletAddress, + // product_url: productUrl, + // name: values.name, + // brand_name: values.brand_name, + // category: { data: values.category }, + // description: values.description, + // price: parseFloat(values.price), + // quantity: parseInt(values.quantity), + // royality: parseInt(values.royality), + // product_info: values.product_info, + // image: values.image, + // }), + // }) + // const phygital = await response.json(); + // localStorage.setItem("PhygitalId", phygital.id); + router.push(`/create-phygital-detail`); } - }; + } else if (!imageError && cid === "") { + toast.warning("Wait for your image to finish upload"); + } + } catch (error) { + console.log("Errors" + error); + toast.warning("Failed to create Collection"); + setLoading(false); + } + } + + const uploadImage = (e: ChangeEvent) => { + const files = e.target.files; + if (files && files.length > 0) { + setFile(files[0]); + uploadFile(files[0]); + } + }; - const removePrefix = (uri: any) => { - return uri.substring(7, uri.length) - } + const removePrefix = (uri: any) => { + return uri.substring(7, uri.length); + }; - return ( - <> - - -
-
-

- Create your Phygital -

-
+ return ( + <> + + +
+
+

Create Phygital

+
-
- -
-

Chain: Base Network

+ + +
+

Chain: Base Network

-
-