Skip to content

Commit

Permalink
Publish shot modal UI
Browse files Browse the repository at this point in the history
  • Loading branch information
JeremyG11 committed Jan 21, 2024
1 parent 826953e commit eb9aec0
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 40 deletions.
2 changes: 1 addition & 1 deletion components/Profile/Blocks/ImageBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const ImageBlock = () => {
if (Array.isArray(boardData.image)) {
mediaSrcUrl = boardData.image[0];
} else if (boardData.image && "files" in boardData.image) {
mediaSrcUrl = createFileUrl(boardData.image.files[0].file);
mediaSrcUrl = createFileUrl(boardData.image.files[0]?.file);
}

return (
Expand Down
50 changes: 50 additions & 0 deletions components/Profile/ProfFeatures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Link from "next/link";
import React from "react";
import { Button } from "../Reusable/Button";

export default function ProfFeatures() {
return (
<div className="space-y-8 border-t-2 border-dashed py-8">
<Link href="" className="text-sm text-gray-500">
Access the features below with Dribbble Pro
<span className="bg-pink-500 uppercase mx-2 px-1 py-0.5 text-xs rounded text-white">
Pro
</span>
</Link>
<div className="flex items-center justify-between">
<div className="space-y-2 text-sm">
<p>Add to project</p>
<p className=" text-gray-500">
Collect and group related work together
</p>
</div>
<Button className="cursor-not-allowed px-3 py-1 md:py-2.5 md:px-5 text-gray-400 text-sm font-semibold bg-gray-50">
Choose project
</Button>
</div>
<div className="flex items-center justify-between">
<div className="space-y-2 text-sm">
<p>Downloads</p>
<p className=" text-gray-500">
Share up to 5 layered files, brushes, and more
</p>
</div>
<Button className="cursor-not-allowed px-3 py-1 md:py-2.5 md:px-5 text-gray-400 text-sm font-semibold bg-gray-50">
Attach files
</Button>
</div>

<div className="flex items-center justify-between">
<div className="space-y-2 text-sm">
<p>Schedule</p>
<p className=" text-gray-500">
Collect and group related work together
</p>
</div>
<Button className="cursor-not-allowed px-3 py-1 md:py-2.5 md:px-5 text-gray-400 text-sm font-semibold bg-gray-50">
Change{" "}
</Button>
</div>
</div>
);
}
111 changes: 101 additions & 10 deletions components/Profile/PublishShotModal.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,123 @@
import React from "react";
"use clientt";
import Image from "next/image";
import React, { useState } from "react";

import Modal from "../Reusable/Modal";
import { useModal } from "@/hooks/modal";
import InputField from "../Reusable/InputField";
import { useBlock } from "@/hooks/toggle";
import ProfFeatures from "./ProfFeatures";
import { Button } from "../Reusable/Button";
import ShotCard from "../Home/ShotCard";
import TagsInput from "../Reusable/InputTag";
import { useUploadThing } from "@/libs/uploadthing";

export function PublishShotModal() {
const { isOpen, type } = useModal();
const { isOpen, type, onClose } = useModal();
const { boardData } = useBlock();
const { startUpload } = useUploadThing("imageUploader");

const isPublishShotModal = isOpen && type === "publishShotModal";

const handleSubmit = async () => {
// let uploadedImageUrl = values.fileUrl;
// if (files.length > 0) {
// if (!uploadedImages) {
// return;
// }
// uploadedImageUrl = uploadedImages[0].url;
// }
// const res = await createShot();
try {
if (boardData["gallery"]?.files) {
const files = boardData["gallery"].files.map(
(fileData) => fileData.file
);
for (const file of files) {
const uploadedImage = await startUpload([file]);
console.log(uploadedImage);
}
}
} catch (error: any) {
console.log("Error", error.message);
}
};
return (
<Modal isOpen={isPublishShotModal} title="Final touches">
<div className="flex items-center pb-10 w-full h-full">
<div className="flex pb-10 w-full h-full">
<div className="">
<ShotCard />
<h1 className="py-1">Thumbnail preview</h1>
<div>
<div className="relative w-64 h-44 group cursor-pointer flex items-end overflow-hidden bg-cover rounded-lg">
<Image
src="https://images.unsplash.com/photo-1603380353725-f8a4d39cc41e?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80"
alt="Thumbnail"
fill
/>
</div>
{/* BOTTOM ICONS AND NAME */}
<div className="w-full pt-1 flex items-center justify-between">
<div className="flex items-center justify-end w-full ">
<button className="flex items-center rounded-full bg-white ml-2 text-white cursor-pointer focus:outline-none">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="w-4 h-4 font-bold text-gray-500 "
>
<path d="M9.653 16.915l-.005-.003-.019-.01a20.759 20.759 0 01-1.162-.682 22.045 22.045 0 01-2.582-1.9C4.045 12.733 2 10.352 2 7.5a4.5 4.5 0 018-2.828A4.5 4.5 0 0118 7.5c0 2.852-2.044 5.233-3.885 6.82a22.049 22.049 0 01-3.744 2.582l-.019.01-.005.003h-.002a.739.739 0 01-.69.001l-.002-.001z" />
</svg>

<p className=" text-gray-500 text-sm ml-1">20</p>
</button>
<button className="flex items-center rounded-full bg-white ml-2 text-white cursor-pointer focus:outline-none">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
className="w-4 h-4 font-bold text-gray-500 "
>
<path d="M10 12.5a2.5 2.5 0 100-5 2.5 2.5 0 000 5z" />
<path
fillRule="evenodd"
d="M.664 10.59a1.651 1.651 0 010-1.186A10.004 10.004 0 0110 3c4.257 0 7.893 2.66 9.336 6.41.147.381.146.804 0 1.186A10.004 10.004 0 0110 17c-4.257 0-7.893-2.66-9.336-6.41zM14 10a4 4 0 11-8 0 4 4 0 018 0z"
clipRule="evenodd"
/>
</svg>
<p className="text-gray-500 text-sm ml-1">6.6k</p>
</button>
</div>
</div>
</div>
</div>
<div className="flex flex-col space-y-5 w-3/5 mx-auto justify-center">
<InputField label="Tags(Maximimum 20)" placeholder="Add Tags" />
<div className="flex flex-col space-y-8 pl-8 w-3/5 mx-auto">
<TagsInput />
<div className="w-full flex items-center space-x-3">
<p>Looking for feedback</p>
<label
htmlFor="feedback"
className="relative ml-2 h-6 w-11 cursor-pointer [-webkit-tap-highlight-color:_transparent]"
>
<input type="checkbox" id="feedback" className="peer sr-only" />
<span className="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-pink-200"></span>
<span className="absolute inset-y-0 start-0 m-1 h-4 w-4 rounded-full bg-gray-500 peer-checked:bg-pink-500 transition-all peer-checked:start-5"></span>
</label>
</div>

<ProfFeatures />
<div className="flex justify-between items-center">
<Button className="py-2 px-5 text-sm font-medium border border-zinc-100">
<Button
onClick={() => onClose()}
className="py-2 px-5 text-sm font-medium border border-zinc-100"
>
Close
</Button>
<div className="inline-flex">
<Button className="py-2 px-5 text-sm font-medium mx-4 bg-zinc-100">
Save as draft
</Button>
<Button className="px-3 py-1 md:py-3 md:px-6 text-white text-sm font-medium bg-primary">
<Button
onClick={handleSubmit}
className="px-3 py-1 md:py-3 md:px-6 text-white text-sm font-medium bg-primary"
>
Publish now
</Button>
</div>
Expand Down
30 changes: 3 additions & 27 deletions components/Profile/ShotUploadForm.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
"use client";
import { useForm } from "react-hook-form";
import React, { useEffect, useState } from "react";
import React, { useState } from "react";

import { AddBlock } from "./AddBlock";
import { useModal } from "@/hooks/modal";
import SideDrawer from "./SideDrawer";
import { Button } from "../Reusable/Button";
import FileUploader from "./FileUploader";
import { useBlock } from "@/hooks/toggle";
import { Shot } from "@/schemas/ShotSchema";
import BlockDisplayCard from "./BlockDisplayCard";
import { createShot } from "@/libs/actions/shot.actions";
import { useUploadThing } from "@/libs/uploadthing";

export default function ShotUploadForm() {
const { isDrawerOpen, boardData } = useBlock();
const isFileSelected = Object.keys(boardData).length !== 0;
const { register, handleSubmit, setValue } = useForm();

const [files, setFiles] = useState<File[]>([]);
const { onOpen, isOpen } = useModal();
Expand All @@ -31,25 +26,6 @@ export default function ShotUploadForm() {
reader.readAsDataURL(new Blob([selectedFile]));
};

const { startUpload } = useUploadThing("imageUploader");

const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
// let uploadedImageUrl = values.fileUrl;
// if (files.length > 0) {
// if (!uploadedImages) {
// return;
// }
// uploadedImageUrl = uploadedImages[0].url;
// }
// const res = await createShot();
if (boardData["gallery"]?.files) {
const uploadedImages = await startUpload(
boardData["gallery"].files.map((fileData) => fileData.file)
);
console.log(uploadedImages);
}
};

return (
<div className="flex w-full min-w-full max-h-screen">
<div className="relative flex-grow overflow-y-auto hide-scroll-bar">
Expand Down Expand Up @@ -79,7 +55,7 @@ export default function ShotUploadForm() {
isDrawerOpen ? "mx-0" : "mx-8 xl:mx-40"
} pt-14 xl:h-full `}
>
<form onSubmit={onSubmit} className="mt-14 w-full xl:h-auto ">
<div className="mt-14 w-full xl:h-auto ">
{isFileSelected ? (
<span className="py-5 flex items-center text-gray-400 text-2xl font-semibold sm:text-4xl xl:max-w-3xl">
<input
Expand Down Expand Up @@ -112,7 +88,7 @@ export default function ShotUploadForm() {
<div className="w-8/12 mx-auto mt-8"></div>
{isFileSelected && <AddBlock />}
</>
</form>
</div>
</div>
</div>
<div className="">
Expand Down
96 changes: 96 additions & 0 deletions components/Reusable/InputTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { FaX } from "react-icons/fa6";
import React, { useState } from "react";

function TagsInput() {
const allSuggestions = [
"ui",
"ux",
"graphic design",
"illustration",
"branding",
"logo",
"typography",
"animation",
"motion design",
"3d",
"app",
];

const [tags, setTags] = useState<string[]>([]);
const [input, setInput] = useState("");
const [suggestions, setSuggestions] = useState<string[]>(allSuggestions);

const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === "Enter" && input && tags.length < 20) {
setTags([...tags, input]);
setInput("");
}
};

const handleDelete = (index: number) => {
const newTags = [...tags];
const removedTag = newTags.splice(index, 1)[0];

setTags(newTags);

if (allSuggestions.includes(removedTag)) {
setSuggestions((prev) => [...prev, removedTag]);
}
};

const handleSuggestionClick = (suggestion: string) => {
if (tags.length < 20) {
setTags([...tags, suggestion]);
setSuggestions(suggestions.filter((s) => s !== suggestion));
}
};

return (
<div className="space-y-2">
<h2>
Tags<span className="text-gray-500 text-sm">(maximimum 20)</span>
</h2>
<div className="flex flex-wrap gap-y-2 w-full placeholder-gray-400/70 dark:placeholder-gray-500 rounded-lg border border-gray-200 bg-white p-2.5 text-gray-700 hover:border-pink-300 hover:outline-none hover:ring hover:ring-pink-200 hover:ring-opacity-40">
{tags.map((tag, index) => (
<div
key={index}
className="mx-0.5 flex items-center justify-center px-1.5 py-0.5 bg-gray-300 rounded"
>
<p className="text-sm px-1 text-black"> {tag}</p>
<button
onClick={() => handleDelete(index)}
className="ml-1 w-4 h-4 rounded-full p-0 flex items-center justify-center text-sm transition-all duration-175 ease-out hover:bg-black hover:text-gray-200 hover:p-0.5 "
>
<FaX className="text-[8px]" />
</button>
</div>
))}
<input
type="text"
value={input}
disabled={tags.length >= 20}
onChange={(e) => setInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder={tags.length > 0 ? "" : "Add tags..."}
className="m-1 h-5 outline-none w-auto min-w-16 placeholder:text-sm"
style={{ width: `${input.length + 1}ch` }}
/>
</div>

<div className="flex flex-wrap items-center">
{suggestions.length > 0 && <p className="text-sm">Suggested:</p>}
{suggestions.map((suggestion, index) => (
<p
key={index}
className="m-1 text-sm leading-3 text-gray-500 cursor-pointer"
onClick={() => handleSuggestionClick(suggestion)}
>
{suggestion},
</p>
))}
</div>
</div>
);
}

export default TagsInput;
4 changes: 2 additions & 2 deletions components/Reusable/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ export default function Modal({ children, isOpen, title }: ModalProps) {
<div
ref={ref}
onClick={handleBackdropClick}
className="bg-black/70 overflow-y-auto overflow-hidden fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full md:inset-0 h-full max-h-full"
className=" bg-black/70 overflow-y-auto hide-scroll-bar fixed top-0 right-0 left-0 z-50 flex justify-center items-center w-full h-full min-h-full"
>
<div className=" relative p-4 w-full xl:max-w-4xl">
<div className="relative p-4 w-full xl:max-w-4xl overflow-y-auto hide-scroll-bar max-h-full">
<div className="relative w-full bg-white rounded-xl shadow-2xl">
<motion.div
animate={isOpen ? "open" : "closed"}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"react-dom": "^18",
"react-hook-form": "^7.49.3",
"react-icons": "^4.12.0",
"react-tag-input-component": "^2.0.2",
"uploadthing": "^6.1.1",
"zod": "^3.22.4",
"zustand": "^4.4.7"
Expand Down
Loading

0 comments on commit eb9aec0

Please sign in to comment.