Merge pull request 'feature/marketplace/artists' (#12) from feature/marketplace/artists into staging
Reviewed-on: http://35.207.46.142/Wodey/wodey-prototype/pulls/12
@ -51,10 +51,12 @@ function layout({ children }: Props) {
|
||||
<Button variant='outline' className='h-8 w-8 md:h-10 md:w-10 p-1 md:p-2' aria-label="Download">
|
||||
<Download size="18" color="#555555" />
|
||||
</Button>
|
||||
<a href="/creator/reader">
|
||||
<Button variant='outline' className='h-8 md:h-10 p-1 md:p-2 flex gap-1 md:gap-2' aria-label="Preview">
|
||||
<Eye size="18" color="#555555" />
|
||||
<p className="hidden md:block">Preview</p>
|
||||
</Button>
|
||||
</a>
|
||||
<Button className='h-8 md:h-10 p-1 md:p-2 flex gap-1 md:gap-2 bg-[#1A237E]' aria-label="Share">
|
||||
<Share2 size="18" color="#ffffff" />
|
||||
<p className="hidden md:block">Share</p>
|
||||
|
||||
182
app/marketplace/artists/_components/Artist_Content.tsx
Normal file
@ -0,0 +1,182 @@
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Heart } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { Checkbox } from '@/components/ui/checkbox';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const mockItems = [
|
||||
{
|
||||
title: 'Business Handshake',
|
||||
type: 'Videos',
|
||||
mediaType: 'video',
|
||||
image: '/v1.png',
|
||||
price: 0.49,
|
||||
},
|
||||
{
|
||||
title: 'Cowboy Howdy',
|
||||
type: 'Fonts',
|
||||
mediaType: 'font',
|
||||
image: '/v2.png',
|
||||
price: 4.99,
|
||||
},
|
||||
{
|
||||
title: 'SEPHORA',
|
||||
type: 'Images',
|
||||
mediaType: 'image',
|
||||
image: '/v3.png',
|
||||
price: 0.19,
|
||||
},
|
||||
{
|
||||
title: 'Gabe Hager',
|
||||
type: 'Videos',
|
||||
mediaType: 'video',
|
||||
image: '/v4.png',
|
||||
price: 9.99,
|
||||
},
|
||||
{
|
||||
title: 'Gabe Hager',
|
||||
type: 'Audios',
|
||||
mediaType: 'audio',
|
||||
image: '/v5.png',
|
||||
price: 3.99,
|
||||
},
|
||||
{
|
||||
title: 'Empty Flat Interior',
|
||||
type: 'Videos',
|
||||
mediaType: 'video',
|
||||
image: '/v6.png',
|
||||
price: 0.49,
|
||||
},
|
||||
{
|
||||
title: 'Black Swan',
|
||||
type: 'Images',
|
||||
mediaType: 'image',
|
||||
image: '/v7.png',
|
||||
price: 0.19,
|
||||
},
|
||||
{
|
||||
title: 'Panda',
|
||||
type: 'Fonts',
|
||||
mediaType: 'font',
|
||||
image: '/v8.png',
|
||||
price: 4.99,
|
||||
},
|
||||
{
|
||||
title: 'Lemon Garden',
|
||||
type: 'Images',
|
||||
mediaType: 'image',
|
||||
image: '/v9.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v10.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v11.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v12.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v13.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v14.png',
|
||||
price: 4.40,
|
||||
},
|
||||
{
|
||||
title: 'Wall Graphics',
|
||||
type: 'Graphics',
|
||||
mediaType: 'graphic',
|
||||
image: '/v15.png',
|
||||
price: 4.40,
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export default function ArtistContent() {
|
||||
return (
|
||||
<div className="w-full min-h-screen">
|
||||
<div className="w-full px-20 mx-auto">
|
||||
<div className="border-b-2 border-[#D1D5DB] mb-8" />
|
||||
{/* Header with greeting and filters inside a card */}
|
||||
<div className="bg-white p-3 rounded-lg shadow-sm py-5 w-full min-h-[46px] flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-8 border-b-2 border-[#D1D5DB]">
|
||||
{/* Greeting */}
|
||||
<div className="flex items-center text-[20px] sm:text-[22px]">
|
||||
<span className="font-[700] text-[#151C4F] mr-1 text-[16px]">Hi Daphne,</span>
|
||||
<span className="text-[#555979] font-[700] text-[16px] ">recommendations for you</span>
|
||||
</div>
|
||||
{/* Filter Chips */}
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{['Images','Videos','Audios','Fonts','Gifs','Graphics'].map((filter) => (
|
||||
<label key={filter} className="flex items-center gap-2 text-[#151C4F] text-[13px] font-[400] cursor-pointer select-none">
|
||||
<Checkbox defaultChecked className="bg-white border-[#E3E6F0] data-[state=checked]:bg-white data-[state=checked]:border-[#151C4F] [&>svg]:text-[#151C4F] data-[state=checked]:text-[#151C4F]" />
|
||||
{filter}
|
||||
</label>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-6">
|
||||
{mockItems.map((item, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative bg-white rounded-sm shadow-sm overflow-hidden group transition hover:shadow-md flex flex-col justify-between"
|
||||
style={{ width: 200, height: 178, gap: 9, borderRadius: 6, paddingBottom: 8 }}
|
||||
>
|
||||
{/* Image */}
|
||||
<div className="relative w-full h-36 flex items-center justify-center bg-gray-100">
|
||||
<Image
|
||||
src={item.image}
|
||||
alt={item.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover' }}
|
||||
className="transition group-hover:scale-105 duration-200"
|
||||
/>
|
||||
{/* Play overlay for video/audio */}
|
||||
{(item.mediaType === 'video' || item.mediaType === 'audio') && (
|
||||
<div className="absolute inset-0 flex items-center justify-center z-10">
|
||||
<Image src="/play.png" alt="Play" width={48} height={48} className="drop-shadow-lg" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{/* Card content */}
|
||||
<div className="px-3 pb-2 pt-1 flex flex-col gap-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-semibold text-sm text-[#151C4F] truncate" title={item.title}>{item.title}</span>
|
||||
<Button variant="ghost" size="icon" className="ml-2">
|
||||
<Heart className="w-5 h-5 text-gray-400 group-hover:text-pink-500 transition" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mt-0.5">
|
||||
<span className="text-xs text-gray-500">In{' '}
|
||||
<span className="capitalize" style={{ color: '#007AFF', fontWeight: 400, fontSize: 12 }}>{item.type}</span>
|
||||
</span>
|
||||
<span className="font-bold text-[#151C4F] text-sm">${item.price.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
76
app/marketplace/artists/_components/Quick_Actions.tsx
Normal file
@ -0,0 +1,76 @@
|
||||
import Image from 'next/image';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const quickActions = [
|
||||
{
|
||||
subtitle: 'Create your own ebook',
|
||||
title: 'Wodey Publishing Studio',
|
||||
image: '/create.png',
|
||||
button: { label: 'Design Now', link: '#' },
|
||||
},
|
||||
{
|
||||
subtitle: 'Unlimited access to',
|
||||
title: '15,000 Fonts',
|
||||
image: '/text.png',
|
||||
button: { label: 'View More', link: '#' },
|
||||
},
|
||||
{
|
||||
subtitle: 'Unlimited access to',
|
||||
title: '25,000 Audios',
|
||||
image: '/paint.png',
|
||||
button: { label: 'View More', link: '#' },
|
||||
},
|
||||
{
|
||||
subtitle: 'Unlimited access to',
|
||||
title: '175,000 Graphics',
|
||||
image: '/brush.png',
|
||||
button: { label: 'View More', link: '#' },
|
||||
},
|
||||
{
|
||||
subtitle: 'Unlimited access to',
|
||||
title: '45,000 Videos',
|
||||
image: '/camera.png',
|
||||
button: { label: 'View More', link: '#' },
|
||||
},
|
||||
];
|
||||
|
||||
export default function QuickActions() {
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
{/* Top linear gradient image bar */}
|
||||
<div className="absolute top-0 left-0 w-full h-3 z-10">
|
||||
<img src="/GradientMesh_Light.png" alt="Gradient Bar" className="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div
|
||||
className="w-full flex flex-col items-center gap-6 py-8 px-20 relative z-20"
|
||||
style={{
|
||||
background: 'radial-gradient(ellipse at 20% 20%, #f5f7fa 60%, #e8eafc 80%, #f7e7fa 100%, #e3f6fd 100%)',
|
||||
minHeight: '100%',
|
||||
width: '100vw',
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center w-full">
|
||||
<div className="flex items-center mr-8">
|
||||
<Image src="/logo.png" alt="Logo" width={240} height={240} className="object-contain" />
|
||||
</div>
|
||||
<div className="flex gap-6 flex-1">
|
||||
{quickActions.map((action, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="bg-white shadow-md flex flex-col items-center justify-center text-center flex-shrink-0"
|
||||
style={{ width: '150px', height: '170px', padding: '11px 15px', borderRadius: 8, justifyContent: 'space-between', overflow: 'hidden' }}
|
||||
>
|
||||
<Image src={action.image} alt={action.title} width={37.43} height={40.8} className="object-contain mx-auto mb-1" />
|
||||
<div className="text-[9px] text-[#151C4F] mb-0.5 w-full font-400">{action.subtitle}</div>
|
||||
<div className="font-[700] text-[10px] text-[#151C4F] mb-0.5 w-full">{action.title}</div>
|
||||
<Button className="w-full h-7 text-[9px] px-0 mt-1 font-400 text-[#1A237E] border-[rgba(48,58,156,0.42)] rounded-sm" variant="outline" asChild>
|
||||
<a href={action.button.link}>{action.button.label}</a>
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
app/marketplace/artists/_components/SearchBar.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Search } from 'lucide-react';
|
||||
|
||||
export default function SearchBar() {
|
||||
return (
|
||||
<div className="flex justify-center w-full my-6">
|
||||
<div
|
||||
className="flex items-center bg-white rounded-xl shadow-md px-4"
|
||||
style={{ width: 613, height: 50 }}
|
||||
>
|
||||
<select className="bg-transparent outline-none text-gray-700 font-medium pr-2 h-full">
|
||||
<option className="text-[14px] font-400">All</option>
|
||||
</select>
|
||||
<span className="mx-2 text-gray-300">|</span>
|
||||
<Search className="w-5 h-5 text-gray-400 mr-2" />
|
||||
<Input
|
||||
type="text"
|
||||
className="flex-1 bg-transparent outline-none text-gray-700 placeholder-gray-400 border-0 shadow-none focus-visible:ring-0 focus-visible:ring-offset-0 h-full"
|
||||
placeholder="Search images, videos, fonts, graphics and more"
|
||||
style={{ height: 48 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
16
app/marketplace/artists/page.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import QuickActions from './_components/Quick_Actions';
|
||||
import ArtistContent from './_components/Artist_Content';
|
||||
import SearchBar from './_components/SearchBar';
|
||||
|
||||
export default function ArtistsPage() {
|
||||
return (
|
||||
<div className="relative bg-[#F3F3F3]">
|
||||
<QuickActions />
|
||||
{/* Overlapping SearchBar */}
|
||||
<div className="w-full flex justify-center relative z-30" style={{ marginTop: '-40px' }}>
|
||||
<SearchBar />
|
||||
</div>
|
||||
<ArtistContent />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
10
app/marketplace/layout.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import MarketplaceNavbar from "@/components/custom/marketplace_Navbar";
|
||||
|
||||
export default function MarketplaceLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="bg-[#F3F3F3]">
|
||||
<MarketplaceNavbar />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
107
app/page.tsx
@ -1,103 +1,12 @@
|
||||
import Image from "next/image";
|
||||
|
||||
import MarketplaceNavbar from "@/components/custom/marketplace_Navbar";
|
||||
import HomeBanner from "@/components/custom/Home_Banner";
|
||||
import BooksFrame from "@/components/custom/books_Frame";
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
||||
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol className="list-inside list-decimal text-sm/6 text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
|
||||
<li className="mb-2 tracking-[-.01em]">
|
||||
Get started by editing{" "}
|
||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-[family-name:var(--font-geist-mono)] font-semibold">
|
||||
app/page.tsx
|
||||
</code>
|
||||
.
|
||||
</li>
|
||||
<li className="tracking-[-.01em]">
|
||||
Save and see your changes instantly.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:w-auto"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
<>
|
||||
<MarketplaceNavbar />
|
||||
<HomeBanner />
|
||||
<BooksFrame />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
87
components/custom/Best_Seller.tsx
Normal file
@ -0,0 +1,87 @@
|
||||
import Image from 'next/image';
|
||||
import { Heart, ChevronRight } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const books = [
|
||||
{
|
||||
title: 'Brutal',
|
||||
author: 'Hoosh Ink',
|
||||
price: '$4.99',
|
||||
cover: '/book1.png',
|
||||
},
|
||||
{
|
||||
title: 'Authority',
|
||||
author: 'Jeff Vandermeer',
|
||||
price: '$11.99',
|
||||
cover: '/book2.png',
|
||||
},
|
||||
{
|
||||
title: 'Babe Hager',
|
||||
author: 'Babe Hager',
|
||||
price: '$2.99',
|
||||
cover: '/book3.png',
|
||||
},
|
||||
{
|
||||
title: 'Never Flinch',
|
||||
author: 'Stephen King',
|
||||
price: '$16.99',
|
||||
cover: '/book4.png',
|
||||
},
|
||||
{
|
||||
title: 'The Obsession',
|
||||
author: 'Jesse Q. Sutanto',
|
||||
price: '$8.99',
|
||||
cover: '/book5.png',
|
||||
},
|
||||
{
|
||||
title: 'Unlikely Story',
|
||||
author: 'Ali Rosen',
|
||||
price: '$2.99',
|
||||
cover: '/book6.png',
|
||||
},
|
||||
{
|
||||
title: 'Thrill Ride',
|
||||
author: 'Amy Ratcliffe',
|
||||
price: '$9.99',
|
||||
cover: '/book7.png',
|
||||
},
|
||||
];
|
||||
|
||||
export default function BestSeller() {
|
||||
return (
|
||||
<div className="w-full py-8 px-20">
|
||||
<div className="flex items-center justify-between mb-2 px-2">
|
||||
<h2 className="text-[15px] font-[600] text-[#151C4F]">Best Sellers</h2>
|
||||
<a href="#" className="text-[#4F8CFF] text-[16px] font-[400] hover:underline flex items-center gap-1">See more <ChevronRight size={16} /></a>
|
||||
</div>
|
||||
<div className="border-b-2 border-[#D1D5DB] mb-6 w-full" />
|
||||
<div className="flex gap-6 overflow-x-auto scrollbar-hide pb-2">
|
||||
{books.map((book, idx) => (
|
||||
<div key={book.title} className="flex flex-col" style={{ minWidth: 158 }}>
|
||||
<div className="relative w-[158px] h-[235px] flex items-center justify-center">
|
||||
<Image
|
||||
src={book.cover}
|
||||
alt={book.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover', borderRadius: 4 }}
|
||||
className="transition group-hover:scale-105 duration-200"
|
||||
/>
|
||||
</div>
|
||||
<div className="px-1 pt-2 flex flex-col gap-1 w-[158px]">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-[400] text-[14px] text-[#151C4F]" title={book.title}>{book.title}</span>
|
||||
<Button variant="ghost" size="icon" className="ml-2">
|
||||
<Heart className="w-5 h-5 text-gray-400 hover:text-pink-500 transition" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mt-0.5">
|
||||
<span className="text-[12px] text-[#555979] font-[400] whitespace-nowrap"><span className="capitalize">{book.author}</span></span>
|
||||
<span className="font-[700] text-[#151C4F] text-[14px] whitespace-nowrap">{book.price}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
40
components/custom/Home_Banner.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import { Button } from "@/components/ui/button";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function HomeBanner() {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="max-w-[1440px] mx-auto px-20 mt-10">
|
||||
<div className="relative h-[240px] md:h-[260px] bg-[rgba(255,248,238,0.9)] rounded-2xl overflow-hidden flex items-center justify-between">
|
||||
{/* Left: Text Content */}
|
||||
<div className="z-10 py-8 flex-1 flex flex-col justify-center pl-16 pr-20">
|
||||
<h1 className="text-[35px] font-[500] text-[#151C4F] mb-2 tracking-tight">
|
||||
1000 BLACK UMBRELLAS
|
||||
</h1>
|
||||
<p className="text-[#151C4F] text-[21px] font-[400] mb-2 max-w-5xl">
|
||||
Poems of absolute nakedness that chase the power of love. Daniel McGinn is<br/> one of the most admired poets in the underground American poetry scene.
|
||||
</p>
|
||||
<Button
|
||||
className="bg-transparent border border-[#151C4F] text-[#151C4F] text-[21px] w-fit px-6 py-3 font-[400] rounded-md mt-4 hover:bg-[#151C4F] hover:text-white transition-all duration-300 cursor-pointer"
|
||||
size="lg"
|
||||
>
|
||||
PURCHASE EBOOK
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Right: Book Cover */}
|
||||
<div className="hidden md:block absolute" style={{ top: '85.44px', left: '986px' }}>
|
||||
<Image
|
||||
src="/book.png"
|
||||
alt="1000 Black Umbrellas Book Cover"
|
||||
width={185}
|
||||
height={275}
|
||||
className="object-contain rounded-xl"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
87
components/custom/New_Release.tsx
Normal file
@ -0,0 +1,87 @@
|
||||
import Image from 'next/image';
|
||||
import { Heart, ChevronRight } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
const books = [
|
||||
{
|
||||
title: 'Brutal',
|
||||
author: 'Hoosh Ink',
|
||||
price: '$4.99',
|
||||
cover: '/book8.png',
|
||||
},
|
||||
{
|
||||
title: 'Authority',
|
||||
author: 'Jeff Vandermeer',
|
||||
price: '$11.99',
|
||||
cover: '/book9.png',
|
||||
},
|
||||
{
|
||||
title: 'Babe Hager',
|
||||
author: 'Babe Hager',
|
||||
price: '$2.99',
|
||||
cover: '/book10.png',
|
||||
},
|
||||
{
|
||||
title: 'Never Flinch',
|
||||
author: 'Stephen King',
|
||||
price: '$16.99',
|
||||
cover: '/book11.png',
|
||||
},
|
||||
{
|
||||
title: 'The Obsession',
|
||||
author: 'Jesse Q. Sutanto',
|
||||
price: '$8.99',
|
||||
cover: '/book12.png',
|
||||
},
|
||||
{
|
||||
title: 'Unlikely Story',
|
||||
author: 'Ali Rosen',
|
||||
price: '$2.99',
|
||||
cover: '/book13.png',
|
||||
},
|
||||
{
|
||||
title: 'Thrill Ride',
|
||||
author: 'Amy Ratcliffe',
|
||||
price: '$9.99',
|
||||
cover: '/book14.png',
|
||||
},
|
||||
];
|
||||
|
||||
export default function NewRelease() {
|
||||
return (
|
||||
<div className="w-full py-8 px-20">
|
||||
<div className="flex items-center justify-between mb-2 px-2">
|
||||
<h2 className="text-[15px] font-[600] text-[#151C4F]">New Release</h2>
|
||||
<a href="#" className="text-[#4F8CFF] text-[16px] font-[400] hover:underline flex items-center gap-1">See more <ChevronRight size={16} /></a>
|
||||
</div>
|
||||
<div className="border-b-2 border-[#D1D5DB] mb-6 w-full" />
|
||||
<div className="flex gap-6 overflow-x-auto scrollbar-hide pb-2">
|
||||
{books.map((book, idx) => (
|
||||
<div key={book.title} className="flex flex-col" style={{ minWidth: 158 }}>
|
||||
<div className="relative w-[158px] h-[235px] flex items-center justify-center">
|
||||
<Image
|
||||
src={book.cover}
|
||||
alt={book.title}
|
||||
fill
|
||||
style={{ objectFit: 'cover', borderRadius: 4 }}
|
||||
className="transition group-hover:scale-105 duration-200"
|
||||
/>
|
||||
</div>
|
||||
<div className="px-1 pt-2 flex flex-col gap-1 w-[158px]">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-[400] text-[14px] text-[#151C4F]" title={book.title}>{book.title}</span>
|
||||
<Button variant="ghost" size="icon" className="ml-2">
|
||||
<Heart className="w-5 h-5 text-gray-400 hover:text-pink-500 transition" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-between mt-0.5">
|
||||
<span className="text-[12px] text-[#555979] font-[400] whitespace-nowrap"><span className="capitalize">{book.author}</span></span>
|
||||
<span className="font-[700] text-[#151C4F] text-[14px] whitespace-nowrap">{book.price}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
components/custom/books_Frame.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
import BestSeller from './Best_Seller';
|
||||
import NewRelease from './New_Release';
|
||||
|
||||
|
||||
|
||||
export default function BooksFrame() {
|
||||
return (
|
||||
<div>
|
||||
<BestSeller />
|
||||
<NewRelease />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
90
components/custom/marketplace_Navbar.tsx
Normal file
@ -0,0 +1,90 @@
|
||||
import Image from 'next/image';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Bell, Heart, ShoppingCart, SquarePen } from 'lucide-react';
|
||||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
|
||||
function MarketplaceNavbar() {
|
||||
return (
|
||||
<nav className="w-full h-[56px] bg-[#010313] flex items-center px-20 justify-between">
|
||||
{/* Logo and Brand */}
|
||||
<div className="flex items-center gap-2 min-w-[180px]">
|
||||
<Image src="/marketplacelogo.png" alt="Woedii Logo" width={40} height={40} className="object-contain" />
|
||||
<span className="text-white text-2xl ml-1 font-normal">Woedii</span>
|
||||
</div>
|
||||
{/* Search Bar */}
|
||||
<div className="flex-1 flex justify-center">
|
||||
<div className="flex items-center bg-[#F2F4F8] rounded-[8px] px-4" style={{ width: 400, height: 40, gap: 8 }}>
|
||||
<svg className="text-[#6B7280] mr-2" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="8.5" cy="8.5" r="5.75"/><path d="M16 16l-3.5-3.5"/></svg>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search images, videos, fonts, graphics and more"
|
||||
className="bg-transparent text-[#6B7280] text-base w-full border-0 focus-visible:ring-0 focus-visible:ring-offset-0 h-full"
|
||||
style={{ height: 40 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Right Side Icons and Profile */}
|
||||
<div className="flex items-center gap-8 min-w-[420px] justify-end">
|
||||
{/* Notifications */}
|
||||
<div className="relative cursor-pointer flex flex-col items-center justify-center">
|
||||
<div className="relative flex items-center justify-center">
|
||||
<Bell size={22} className="text-white" />
|
||||
<span className="absolute -top-1 -right-1 w-[9px] h-[9px] bg-[#FF3B30] rounded-full border-[1.5px] border-[#020316]" />
|
||||
</div>
|
||||
<span className="text-xs text-white mt-1">Notifications</span>
|
||||
</div>
|
||||
{/* Favorites */}
|
||||
<div className="cursor-pointer flex flex-col items-center justify-center">
|
||||
<Heart size={22} className="text-white" />
|
||||
<span className="text-xs text-white mt-1">Favorites</span>
|
||||
</div>
|
||||
{/* Cart */}
|
||||
<div className="cursor-pointer flex flex-col items-center justify-center">
|
||||
<ShoppingCart size={22} className="text-white" />
|
||||
<span className="text-xs text-white mt-1">Cart</span>
|
||||
</div>
|
||||
{/* Profile */}
|
||||
<div className="cursor-pointer flex flex-col items-center justify-center">
|
||||
<div className="flex items-center justify-center">
|
||||
<Avatar className="w-6 h-6">
|
||||
<AvatarImage src="/avatar.png" alt="Profile" />
|
||||
<AvatarFallback>U</AvatarFallback>
|
||||
</Avatar>
|
||||
</div>
|
||||
<span className="text-xs text-white mt-1">My Profile</span>
|
||||
</div>
|
||||
{/* Create Button */}
|
||||
<a href="/creator">
|
||||
<Button className="flex items-center gap-2 bg-[#0093A5] text-white px-5 py-2 rounded-lg font-medium text-base transition-colors ml-4 hover:bg-[#007a87] cursor-pointer" type="button">
|
||||
<SquarePen size={18} />
|
||||
Create
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
function MarketplaceSecondaryMenu() {
|
||||
return (
|
||||
<div className="w-full bg-[#010313] flex items-center px-20 h-7 border-t border-white/20 p-5">
|
||||
<ul className="flex gap-10 text-white text-sm font-normal">
|
||||
<li className="cursor-pointer">Images</li>
|
||||
<li className="cursor-pointer">Videos</li>
|
||||
<li className="cursor-pointer">Audios</li>
|
||||
<li className="cursor-pointer">Gifs</li>
|
||||
<li className="cursor-pointer">Fonts</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function MarketplaceNavbarWithMenu() {
|
||||
return (
|
||||
<>
|
||||
<MarketplaceNavbar />
|
||||
<MarketplaceSecondaryMenu />
|
||||
</>
|
||||
);
|
||||
}
|
||||
32
components/ui/checkbox.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
||||
import { CheckIcon } from "lucide-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Checkbox({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
||||
return (
|
||||
<CheckboxPrimitive.Root
|
||||
data-slot="checkbox"
|
||||
className={cn(
|
||||
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator
|
||||
data-slot="checkbox-indicator"
|
||||
className="flex items-center justify-center text-current transition-none"
|
||||
>
|
||||
<CheckIcon className="size-3.5" />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export { Checkbox }
|
||||
@ -12,6 +12,7 @@
|
||||
"@radix-ui/react-avatar": "^1.1.7",
|
||||
"@radix-ui/react-context-menu": "^2.2.12",
|
||||
"@radix-ui/react-hover-card": "^1.1.11",
|
||||
"@radix-ui/react-checkbox": "^1.2.3",
|
||||
"@radix-ui/react-slot": "^1.2.0",
|
||||
"@radix-ui/react-tabs": "^1.1.9",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
|
||||
@ -11,6 +11,9 @@ importers:
|
||||
'@radix-ui/react-avatar':
|
||||
specifier: ^1.1.7
|
||||
version: 1.1.7(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-checkbox':
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-context-menu':
|
||||
specifier: ^2.2.12
|
||||
version: 2.2.12(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
@ -382,6 +385,19 @@ packages:
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-checkbox@1.2.3':
|
||||
resolution: {integrity: sha512-pHVzDYsnaDmBlAuwim45y3soIN8H4R7KbkSVirGhXO+R/kO2OLCe0eucUEbddaTcdMHHdzcIGHtZSMSQlA+apw==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
'@types/react-dom': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-collection@1.1.4':
|
||||
resolution: {integrity: sha512-cv4vSf7HttqXilDnAnvINd53OTl1/bjUYVZrkFnA7nwmY9Ob2POUy0WY0sfqBAe1s5FyKsyceQlqiEGPYNTadg==}
|
||||
peerDependencies:
|
||||
@ -646,6 +662,15 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-previous@1.1.1':
|
||||
resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==}
|
||||
peerDependencies:
|
||||
'@types/react': '*'
|
||||
react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
'@radix-ui/react-use-rect@1.1.1':
|
||||
resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==}
|
||||
peerDependencies:
|
||||
@ -2419,6 +2444,22 @@ snapshots:
|
||||
'@types/react': 19.1.2
|
||||
'@types/react-dom': 19.1.2(@types/react@19.1.2)
|
||||
|
||||
'@radix-ui/react-checkbox@1.2.3(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.2)(react@19.1.0)
|
||||
'@radix-ui/react-presence': 1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-primitive': 2.1.0(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.2)(react@19.1.0)
|
||||
'@radix-ui/react-use-previous': 1.1.1(@types/react@19.1.2)(react@19.1.0)
|
||||
'@radix-ui/react-use-size': 1.1.1(@types/react@19.1.2)(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.2
|
||||
'@types/react-dom': 19.1.2(@types/react@19.1.2)
|
||||
|
||||
'@radix-ui/react-collection@1.1.4(@types/react-dom@19.1.2(@types/react@19.1.2))(@types/react@19.1.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.2)(react@19.1.0)
|
||||
@ -2671,6 +2712,12 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.2
|
||||
|
||||
'@radix-ui/react-use-previous@1.1.1(@types/react@19.1.2)(react@19.1.0)':
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.2
|
||||
|
||||
'@radix-ui/react-use-rect@1.1.1(@types/react@19.1.2)(react@19.1.0)':
|
||||
dependencies:
|
||||
'@radix-ui/rect': 1.1.1
|
||||
|
||||
BIN
public/GradientMesh_Light.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
public/avatar.png
Normal file
|
After Width: | Height: | Size: 994 KiB |
BIN
public/book.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
BIN
public/book1.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
public/book10.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
public/book11.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
public/book12.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
public/book13.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
public/book14.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
public/book2.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
public/book3.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
public/book4.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
public/book5.png
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
public/book6.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
public/book7.png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
public/book8.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/book9.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
public/brush.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/camera.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/create.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/marketplacelogo.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/paint.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/play.png
Normal file
|
After Width: | Height: | Size: 470 B |
BIN
public/text.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/titlelogo.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/v1.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
public/v10.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/v11.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/v12.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
public/v13.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
public/v14.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
public/v15.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
public/v2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/v3.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
public/v4.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
public/v5.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/v6.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
public/v7.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
public/v8.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
public/v9.png
Normal file
|
After Width: | Height: | Size: 43 KiB |