Merge pull request 'feature/slider-docs' (#7) from feature/slider-docs into main
Reviewed-on: http://35.207.46.142/Wodey/woedii/pulls/7
270
app/docs/page.tsx
Normal file
@ -0,0 +1,270 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import ReactMarkdown, { Components } from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
||||
const ReadmePage = () => {
|
||||
const readmeContent = `
|
||||
## 📘 WODEY Deliverables Overview
|
||||
|
||||
Welcome to your WODEY UI/UX design package. This page provides everything your team needs to understand, preview, and implement the design assets developed for the WODEY Publishing Ecosystem.
|
||||
|
||||
## 📂 What’s Included
|
||||
|
||||
Your deliverables include high-fidelity UI mockups, design system components, and documentation that collectively represent the full user journey across all major WODEY touchpoints.
|
||||
|
||||
| Section | Description |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| 01_Homepage | The landing experience for www.wodey.books including hero sections, genre browsing, and ebook discovery |
|
||||
| 02_Author Studio | UI for authors to create, edit, preview, and publish multimedia ebooks |
|
||||
| 03_Reader App | Reader-facing immersive interface with scroll & flip view modes |
|
||||
| 04_Artist Marketplace | Asset browsing, upload flow, and commission request screens |
|
||||
| 05_Advertiser Portal | Campaign setup, keyword targeting, and performance dashboards |
|
||||
| 06_WODEY_Wallet | Revenue dashboard tracking ebook sales and ad earnings |
|
||||
| 07_Design System | Colors, typography, button states, spacing, and reusable components |
|
||||
| 08_Prototype_Flow | Clickable user journey demo |
|
||||
|
||||
## 🛠 How to Use These Files
|
||||
|
||||
Preview the Screens: Scroll through the design sections in logical flow
|
||||
|
||||
Download Assets: Use the "Download All Mockups" button to access the .zip file
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
[Live Preview URL](https://woedii.yoursoftwareengineers.com)
|
||||
|
||||
[Download Full Zip File by clicking on the download icon](https://woedii.yoursoftwareengineers.com/slider)
|
||||
|
||||
## 🤝 Support
|
||||
|
||||
If you need help integrating these designs into code or want to schedule a handoff session, please contact:
|
||||
|
||||
UI/UX Design Lead: Daphne Augustine ([daphne@yoursoftwareengineers.com](mailto:daphne@yoursoftwareengineers.com))
|
||||
|
||||
Development Lead: Yussif Yahuza ([yussif@yoursoftwareengineers.com](mailto:yussif@yoursoftwareengineers.com))
|
||||
`;
|
||||
|
||||
const components: Components = {
|
||||
h1: ({ node, ...props }) => (
|
||||
<h1
|
||||
style={{
|
||||
fontSize: "2.2em",
|
||||
fontWeight: "600",
|
||||
marginTop: "1.2em",
|
||||
marginBottom: "0.6em",
|
||||
borderBottom: "1px solid #eaeaea",
|
||||
paddingBottom: "0.3em",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h2: ({ node, ...props }) => (
|
||||
<h2
|
||||
style={{
|
||||
fontSize: "1.8em",
|
||||
fontWeight: "600",
|
||||
marginTop: "1.2em",
|
||||
marginBottom: "0.6em",
|
||||
borderBottom: "1px solid #eaeaea",
|
||||
paddingBottom: "0.3em",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
h3: ({ node, ...props }) => (
|
||||
<h3
|
||||
style={{
|
||||
fontSize: "1.5em",
|
||||
fontWeight: "600",
|
||||
marginTop: "1.2em",
|
||||
marginBottom: "0.6em",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
p: ({ node, ...props }) => (
|
||||
<p style={{ marginBottom: "1.2em", lineHeight: "1.8" }} {...props} />
|
||||
),
|
||||
a: ({ node, ...props }) => (
|
||||
<a
|
||||
style={{ color: "#0366d6", textDecoration: "none", fontWeight: "500" }}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
ul: ({ node, ...props }) => (
|
||||
<ul
|
||||
style={{
|
||||
paddingLeft: "1.5em",
|
||||
marginBottom: "1.2em",
|
||||
listStyleType: "disc",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
ol: ({ node, ...props }) => (
|
||||
<ol
|
||||
style={{
|
||||
paddingLeft: "1.5em",
|
||||
marginBottom: "1.2em",
|
||||
listStyleType: "decimal",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
li: ({ node, ...props }) => (
|
||||
<li style={{ marginBottom: "0.4em" }} {...props} />
|
||||
),
|
||||
table: ({ node, ...props }) => (
|
||||
<table
|
||||
style={{
|
||||
width: "100%",
|
||||
borderCollapse: "collapse",
|
||||
marginBottom: "1.2em",
|
||||
boxShadow: "0 1px 3px rgba(0,0,0,0.08)",
|
||||
border: "1px solid #dfe2e5",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
th: ({ node, ...props }) => (
|
||||
<th
|
||||
style={{
|
||||
border: "1px solid #dfe2e5",
|
||||
padding: "0.6em 0.8em",
|
||||
textAlign: "left",
|
||||
backgroundColor: "#f6f8fa",
|
||||
fontWeight: "600",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
td: ({ node, ...props }) => (
|
||||
<td
|
||||
style={{
|
||||
border: "1px solid #dfe2e5",
|
||||
padding: "0.6em 0.8em",
|
||||
textAlign: "left",
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
),
|
||||
pre: ({ node, children, ...props }) => (
|
||||
<pre
|
||||
style={{
|
||||
backgroundColor: "#f6f8fa",
|
||||
padding: "1em",
|
||||
borderRadius: "6px",
|
||||
overflowX: "auto",
|
||||
fontSize: "0.9em",
|
||||
lineHeight: "1.5",
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</pre>
|
||||
),
|
||||
code: (props) => {
|
||||
// Using `props: any` and casting to bypass TypeScript error with `inline` prop.
|
||||
const {
|
||||
node,
|
||||
inline: isInline,
|
||||
className,
|
||||
children,
|
||||
// Destructure known non-HTML props from react-markdown to prevent them from being spread onto the <code> tag
|
||||
index,
|
||||
siblingCount,
|
||||
ordered,
|
||||
checked,
|
||||
style: _style, // if style is passed in props, avoid conflict with style object below
|
||||
...htmlProps // Spread remaining props, assuming they are valid HTML attributes for <code>
|
||||
} = props as any;
|
||||
|
||||
const codeStyleBase = {
|
||||
fontFamily:
|
||||
'SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace',
|
||||
};
|
||||
|
||||
if (isInline) {
|
||||
return (
|
||||
<code
|
||||
className={className}
|
||||
style={{
|
||||
...codeStyleBase,
|
||||
backgroundColor: "rgba(27,31,35,0.07)", // Slightly adjusted for better visibility
|
||||
padding: "0.2em 0.4em",
|
||||
margin: "0 0.1em",
|
||||
fontSize: "85%",
|
||||
borderRadius: "3px",
|
||||
}}
|
||||
{...htmlProps}
|
||||
>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
}
|
||||
|
||||
// For block code (inside <pre>)
|
||||
return (
|
||||
<code
|
||||
className={className} // className might contain "language-js" etc.
|
||||
style={{
|
||||
...codeStyleBase,
|
||||
// Most styling for block code is handled by the <pre> wrapper
|
||||
// However, ensure no extra padding/margin if pre handles it
|
||||
padding: 0,
|
||||
backgroundColor: "transparent", // Pre has the background
|
||||
}}
|
||||
{...htmlProps}
|
||||
>
|
||||
{children}
|
||||
</code>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: "2rem",
|
||||
fontFamily:
|
||||
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
||||
lineHeight: "1.7",
|
||||
color: "#24292e",
|
||||
backgroundColor: "#ffffff",
|
||||
maxWidth: "800px",
|
||||
margin: "40px auto",
|
||||
boxShadow: "0 4px 12px rgba(0,0,0,0.08)",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
>
|
||||
<ReactMarkdown components={components} remarkPlugins={[remarkGfm]}>
|
||||
{readmeContent}
|
||||
</ReactMarkdown>
|
||||
<a
|
||||
href="http://35.207.46.142/Wodey/woedii"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{
|
||||
display: "inline-block",
|
||||
marginTop: "2.5rem",
|
||||
padding: "0.8rem 1.6rem",
|
||||
backgroundColor: "#0366d6",
|
||||
color: "white",
|
||||
textDecoration: "none",
|
||||
borderRadius: "6px",
|
||||
fontWeight: "600",
|
||||
textAlign: "center",
|
||||
transition: "background-color 0.2s ease-in-out",
|
||||
}}
|
||||
onMouseOver={(e) => (e.currentTarget.style.backgroundColor = "#005cc5")}
|
||||
onMouseOut={(e) => (e.currentTarget.style.backgroundColor = "#0366d6")}
|
||||
>
|
||||
Go to Project Repo
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReadmePage;
|
||||
64
app/slider/page.tsx
Normal file
@ -0,0 +1,64 @@
|
||||
import ImageSlider from "@/components/custom/ImageSlider";
|
||||
|
||||
const SliderPage = () => {
|
||||
const images = [
|
||||
"/assets/1.png",
|
||||
"/assets/2.png",
|
||||
"/assets/3.png",
|
||||
"/assets/4.png",
|
||||
"/assets/5.png",
|
||||
"/assets/6.png",
|
||||
"/assets/7.png",
|
||||
"/assets/8.png",
|
||||
"/assets/9.png",
|
||||
"/assets/10.png",
|
||||
"/assets/11.png",
|
||||
"/assets/12.png",
|
||||
"/assets/13.png",
|
||||
"/assets/14.png",
|
||||
"/assets/15.png",
|
||||
"/assets/16.png",
|
||||
"/assets/17.png",
|
||||
"/assets/18.png",
|
||||
"/assets/19.png",
|
||||
"/assets/20.png",
|
||||
"/assets/21.png",
|
||||
"/assets/22.png",
|
||||
"/assets/23.png",
|
||||
"/assets/24.png",
|
||||
"/assets/25.png",
|
||||
"/assets/26.png",
|
||||
"/assets/27.png",
|
||||
"/assets/28.png",
|
||||
"/assets/29.png",
|
||||
"/assets/30.png",
|
||||
"/assets/31.png",
|
||||
"/assets/32.png",
|
||||
"/assets/33.png",
|
||||
"/assets/34.png",
|
||||
"/assets/35.png",
|
||||
"/assets/36.png",
|
||||
"/assets/37.png",
|
||||
"/assets/38.png",
|
||||
"/assets/39.png",
|
||||
"/assets/40.png",
|
||||
"/assets/41.png",
|
||||
"/assets/42.png",
|
||||
"/assets/43.png",
|
||||
"/assets/44.png",
|
||||
"/assets/45.png",
|
||||
"/assets/46.png",
|
||||
"/assets/47.png",
|
||||
"/assets/48.png",
|
||||
"/assets/49.png",
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<h1 className="text-3xl font-bold text-center mb-8">Image Slider</h1>
|
||||
<ImageSlider images={images} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SliderPage;
|
||||
176
components/custom/ImageSlider.tsx
Normal file
@ -0,0 +1,176 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ChevronLeft, ChevronRight, ArrowLeft, Download } from "lucide-react"; // Added Download
|
||||
import { useRouter } from "next/navigation";
|
||||
import JSZip from "jszip";
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
interface ImageSliderProps {
|
||||
images: string[];
|
||||
}
|
||||
|
||||
const ImageSlider: React.FC<ImageSliderProps> = ({ images }) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
const [isHovered, setIsHovered] = useState(false); // New state for hover
|
||||
const router = useRouter();
|
||||
|
||||
const goToPrevious = () => {
|
||||
const isFirstImage = currentIndex === 0;
|
||||
const newIndex = isFirstImage ? images.length - 1 : currentIndex - 1;
|
||||
setCurrentIndex(newIndex);
|
||||
};
|
||||
|
||||
const goToNext = () => {
|
||||
const isLastImage = currentIndex === images.length - 1;
|
||||
const newIndex = isLastImage ? 0 : currentIndex + 1;
|
||||
setCurrentIndex(newIndex);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let timer: NodeJS.Timeout;
|
||||
if (!isHovered) {
|
||||
// Only set timer if not hovered
|
||||
timer = setTimeout(() => {
|
||||
goToNext();
|
||||
}, 5000); // Change image every 5 seconds
|
||||
}
|
||||
return () => clearTimeout(timer);
|
||||
}, [currentIndex, images.length, isHovered, goToNext]); // Added isHovered and goToNext to dependency array
|
||||
|
||||
const handleDownloadAll = async () => {
|
||||
if (!images || images.length === 0) return;
|
||||
setIsDownloading(true);
|
||||
const zip = new JSZip();
|
||||
try {
|
||||
for (let i = 0; i < images.length; i++) {
|
||||
const response = await fetch(images[i]);
|
||||
const blob = await response.blob();
|
||||
// Extract filename from path, or use index as fallback
|
||||
const filename =
|
||||
images[i].substring(images[i].lastIndexOf("/") + 1) ||
|
||||
`image_${i + 1}.png`;
|
||||
zip.file(filename, blob);
|
||||
}
|
||||
const zipBlob = await zip.generateAsync({ type: "blob" });
|
||||
saveAs(zipBlob, "images.zip");
|
||||
} catch (error) {
|
||||
console.error("Error zipping images:", error);
|
||||
// Handle error (e.g., show a notification to the user)
|
||||
} finally {
|
||||
setIsDownloading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (!images || images.length === 0) {
|
||||
return <p>No images to display.</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative w-full max-w-2xl mx-auto flex flex-col items-center rounded-lg shadow-lg bg-gray-100 dark:bg-gray-700 p-4"
|
||||
onMouseEnter={() => setIsHovered(true)} // Set hovered to true
|
||||
onMouseLeave={() => setIsHovered(false)} // Set hovered to false
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => router.back()}
|
||||
className="absolute top-4 left-4 text-black bg-black bg-opacity-50 hover:bg-opacity-75 z-10" // Added z-10
|
||||
aria-label="Go back"
|
||||
>
|
||||
<ArrowLeft className="h-6 w-6" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={handleDownloadAll}
|
||||
disabled={isDownloading}
|
||||
className="absolute top-4 right-4 bg-black bg-opacity-50 text-black hover:bg-opacity-75 z-10"
|
||||
aria-label="Download all images"
|
||||
>
|
||||
{isDownloading ? (
|
||||
<svg
|
||||
className="animate-spin h-5 w-5 text-white"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
></circle>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
></path>
|
||||
</svg>
|
||||
) : (
|
||||
<Download className="h-6 w-6" />
|
||||
)}
|
||||
</Button>
|
||||
<div className="relative w-full overflow-hidden rounded-t-lg mt-12">
|
||||
{" "}
|
||||
{/* Added mt-12 to make space for back button */}
|
||||
<div
|
||||
className="flex transition-transform duration-500 ease-in-out"
|
||||
style={{ transform: `translateX(-${currentIndex * 100}%)` }}
|
||||
>
|
||||
{images.map((src, index) => (
|
||||
<div key={index} className="w-full flex-shrink-0 h-96 relative">
|
||||
<Image
|
||||
src={src}
|
||||
alt={`Slide ${index + 1}`}
|
||||
fill // Changed from layout="fill"
|
||||
objectFit="contain"
|
||||
priority={index === 0}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="absolute top-1/2 left-2 transform -translate-y-1/2 bg-black bg-opacity-50 text-white hover:bg-opacity-75"
|
||||
onClick={goToPrevious}
|
||||
>
|
||||
<ChevronLeft className="h-6 w-6" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="absolute top-1/2 right-2 transform -translate-y-1/2 bg-black bg-opacity-50 text-white hover:bg-opacity-75"
|
||||
onClick={goToNext}
|
||||
>
|
||||
<ChevronRight className="h-6 w-6" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-2 pt-4 pb-1">
|
||||
{" "}
|
||||
{/* Changed py-4 to pt-4 pb-1 to move dots lower */}
|
||||
{images.map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className={`w-3 h-3 rounded-full ${
|
||||
currentIndex === index
|
||||
? "bg-blue-500"
|
||||
: "bg-gray-400 hover:bg-gray-500"
|
||||
}`}
|
||||
onClick={() => setCurrentIndex(index)}
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageSlider;
|
||||
@ -1,9 +1,14 @@
|
||||
import { Bell, Menu } from 'lucide-react';
|
||||
import { Search } from 'lucide-react';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Dispatch, SetStateAction } from 'react';
|
||||
import { Bell, Menu } from "lucide-react";
|
||||
import { Search } from "lucide-react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Navbar({ setDrawerOpen }: { setDrawerOpen?: Dispatch<SetStateAction<boolean>> }) {
|
||||
export default function Navbar({
|
||||
setDrawerOpen,
|
||||
}: {
|
||||
setDrawerOpen?: Dispatch<SetStateAction<boolean>>;
|
||||
}) {
|
||||
return (
|
||||
<div className="flex items-center justify-between w-full h-[52px] xs:h-[56px] sm:h-[64px] md:h-[75px] bg-white px-2 xs:px-3 sm:px-4 md:px-6 lg:px-10">
|
||||
{/* Hamburger menu for mobile */}
|
||||
@ -29,7 +34,10 @@ export default function Navbar({ setDrawerOpen }: { setDrawerOpen?: Dispatch<Set
|
||||
</div>
|
||||
<div className="flex items-center gap-1 xs:gap-2 sm:gap-3 md:gap-4 lg:gap-6">
|
||||
<div className="relative cursor-pointer">
|
||||
<Bell size={16} className="text-[#222] xs:text-[18px] sm:text-[20px] md:text-[22px]" />
|
||||
<Bell
|
||||
size={16}
|
||||
className="text-[#222] xs:text-[18px] sm:text-[20px] md:text-[22px]"
|
||||
/>
|
||||
<span className="absolute top-[-2px] right-0 w-1 h-1 xs:w-1.5 xs:h-1.5 sm:w-2 sm:h-2 bg-[#FF3B30] rounded-full border-[1.5px] border-white" />
|
||||
</div>
|
||||
<div className="flex items-center cursor-pointer">
|
||||
@ -40,7 +48,11 @@ export default function Navbar({ setDrawerOpen }: { setDrawerOpen?: Dispatch<Set
|
||||
+
|
||||
</div>
|
||||
</div>
|
||||
<Link href="/creator">Creator</Link>
|
||||
<Link href="/marketplace/artists">Marketplace</Link>
|
||||
<Link href="/slider">Slider</Link>
|
||||
<Link href="/docs">Docs</Link>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
'use client';
|
||||
"use client";
|
||||
|
||||
import Image from 'next/image';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Bell, Heart, ShoppingCart, SquarePen, Menu } from 'lucide-react';
|
||||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useState } from 'react';
|
||||
import Image from "next/image";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Bell, Heart, ShoppingCart, SquarePen, Menu } from "lucide-react";
|
||||
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
function MarketplaceNavbar() {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
@ -15,12 +16,20 @@ function MarketplaceNavbar() {
|
||||
<div className="container-main h-[56px] flex items-center justify-between px-4 md:px-6">
|
||||
{/* Logo and Brand */}
|
||||
<div className="flex items-center gap-2 min-w-[120px] md:min-w-[180px]">
|
||||
<Image src="/marketplacelogo.png" alt="Woedii Logo" width={40} height={40} className="object-contain" />
|
||||
<span className="text-white text-xl md:text-2xl ml-1 font-normal">Wodey</span>
|
||||
<Image
|
||||
src="/marketplacelogo.png"
|
||||
alt="Woedii Logo"
|
||||
width={40}
|
||||
height={40}
|
||||
className="object-contain"
|
||||
/>
|
||||
<span className="text-white text-xl md:text-2xl ml-1 font-normal">
|
||||
Wodey
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
<button
|
||||
<button
|
||||
className="md:hidden text-white"
|
||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||
>
|
||||
@ -29,8 +38,23 @@ function MarketplaceNavbar() {
|
||||
|
||||
{/* Search Bar - Hidden on mobile */}
|
||||
<div className="hidden md:flex flex-1 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>
|
||||
<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"
|
||||
@ -72,7 +96,10 @@ function MarketplaceNavbar() {
|
||||
</div>
|
||||
{/* Create Button */}
|
||||
<a href="/creator">
|
||||
<Button className="flex items-center gap-2 bg-[#0093A5] text-white px-3 md:px-5 py-2 rounded-lg font-medium text-sm md:text-base transition-colors ml-2 md:ml-4 hover:bg-[#007a87] cursor-pointer" type="button">
|
||||
<Button
|
||||
className="flex items-center gap-2 bg-[#0093A5] text-white px-3 md:px-5 py-2 rounded-lg font-medium text-sm md:text-base transition-colors ml-2 md:ml-4 hover:bg-[#007a87] cursor-pointer"
|
||||
type="button"
|
||||
>
|
||||
<SquarePen size={18} />
|
||||
<span className="hidden sm:inline">Create</span>
|
||||
</Button>
|
||||
@ -80,11 +107,32 @@ function MarketplaceNavbar() {
|
||||
</div>
|
||||
|
||||
{/* Mobile Menu */}
|
||||
<div className={`absolute top-[56px] left-0 right-0 bg-[#010313] z-50 md:hidden transition-all duration-300 ease-in-out transform ${isMenuOpen ? 'translate-y-0 opacity-100' : '-translate-y-4 opacity-0 pointer-events-none'}`}>
|
||||
<div
|
||||
className={`absolute top-[56px] left-0 right-0 bg-[#010313] z-50 md:hidden transition-all duration-300 ease-in-out transform ${
|
||||
isMenuOpen
|
||||
? "translate-y-0 opacity-100"
|
||||
: "-translate-y-4 opacity-0 pointer-events-none"
|
||||
}`}
|
||||
>
|
||||
<div className="container-main py-4">
|
||||
{/* Mobile Search */}
|
||||
<div className="flex items-center bg-[#F2F4F8] rounded-[8px] px-4 mb-4" style={{ 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>
|
||||
<div
|
||||
className="flex items-center bg-[#F2F4F8] rounded-[8px] px-4 mb-4"
|
||||
style={{ 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..."
|
||||
@ -137,6 +185,16 @@ function MarketplaceSecondaryMenu() {
|
||||
<li className="cursor-pointer">Audios</li>
|
||||
<li className="cursor-pointer">Gifs</li>
|
||||
<li className="cursor-pointer">Fonts</li>
|
||||
<li className="cursor-pointer">
|
||||
<Link href="/slider" className="text-white hover:text-gray-300">
|
||||
Slider
|
||||
</Link>
|
||||
</li>
|
||||
<li className="cursor-pointer">
|
||||
<Link href="/docs" className="text-white hover:text-gray-300">
|
||||
Docs
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
38
docs/deliverables.md
Normal file
@ -0,0 +1,38 @@
|
||||
📘 WODEY Deliverables Overview
|
||||
|
||||
Welcome to your WODEY UI/UX design package. This page provides everything your team needs to understand, preview, and implement the design assets developed for the WODEY Publishing Ecosystem.
|
||||
|
||||
📂 What’s Included
|
||||
|
||||
Your deliverables include high-fidelity UI mockups, design system components, and documentation that collectively represent the full user journey across all major WODEY touchpoints.
|
||||
|
||||
| Section | Description |
|
||||
| --------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| 01_Homepage | The landing experience for www.wodey.books including hero sections, genre browsing, and ebook discovery |
|
||||
| 02_Author Studio | UI for authors to create, edit, preview, and publish multimedia ebooks |
|
||||
| 03_Reader App | Reader-facing immersive interface with scroll & flip view modes |
|
||||
| 04_Artist Marketplace | Asset browsing, upload flow, and commission request screens |
|
||||
| 05_Advertiser Portal | Campaign setup, keyword targeting, and performance dashboards |
|
||||
| 06_WODEY_Wallet | Revenue dashboard tracking ebook sales and ad earnings |
|
||||
| 07_DesignS ystem | Colors, typography, button states, spacing, and reusable components |
|
||||
| 08_Prototype_Flow | Clickable user journey demo |
|
||||
|
||||
🛠 How to Use These Files
|
||||
|
||||
Preview the Screens: Scroll through the design sections in logical flow
|
||||
|
||||
Download Assets: Use the "Download All Mockups" button to access the .zip file
|
||||
|
||||
🔗 Links
|
||||
|
||||
[Live Preview URL](https://woedii.yoursoftwareengineers.com)
|
||||
|
||||
[Download Full Zip File by clicking on the download icon](https://woedii.yoursoftwareengineers.com/slider)
|
||||
|
||||
🤝 Support
|
||||
|
||||
If you need help integrating these designs into code or want to schedule a handoff session, please contact:
|
||||
|
||||
UI/UX Design Lead: Daphne Augustine ([daphne@yoursoftwareengineers.com](mailto:daphne@yoursoftwareengineers.com))
|
||||
|
||||
Development Lead: Yussif Yahuza ([yussif@yoursoftwareengineers.com](mailto:yussif@yoursoftwareengineers.com))
|
||||
@ -18,17 +18,22 @@
|
||||
"@radix-ui/react-tooltip": "^1.2.4",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"iconsax-react": "^0.0.8",
|
||||
"jszip": "^3.10.1",
|
||||
"lucide-react": "^0.503.0",
|
||||
"next": "15.3.1",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-icons": "^5.5.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tailwind-merge": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3",
|
||||
"@tailwindcss/postcss": "^4",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
|
||||
975
pnpm-lock.yaml
BIN
public/assets/1.png
Normal file
|
After Width: | Height: | Size: 331 KiB |
BIN
public/assets/10.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
public/assets/11.png
Normal file
|
After Width: | Height: | Size: 452 KiB |
BIN
public/assets/12.png
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
public/assets/13.png
Normal file
|
After Width: | Height: | Size: 206 KiB |
BIN
public/assets/14.png
Normal file
|
After Width: | Height: | Size: 231 KiB |
BIN
public/assets/15.png
Normal file
|
After Width: | Height: | Size: 590 KiB |
BIN
public/assets/16.png
Normal file
|
After Width: | Height: | Size: 576 KiB |
BIN
public/assets/17.png
Normal file
|
After Width: | Height: | Size: 261 KiB |
BIN
public/assets/18.png
Normal file
|
After Width: | Height: | Size: 321 KiB |
BIN
public/assets/19.png
Normal file
|
After Width: | Height: | Size: 313 KiB |
BIN
public/assets/2.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
public/assets/20.png
Normal file
|
After Width: | Height: | Size: 360 KiB |
BIN
public/assets/21.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
public/assets/22.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/assets/23.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
public/assets/24.png
Normal file
|
After Width: | Height: | Size: 254 KiB |
BIN
public/assets/25.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/26.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
public/assets/27.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/28.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/29.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/assets/3.png
Normal file
|
After Width: | Height: | Size: 355 KiB |
BIN
public/assets/30.png
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
public/assets/31.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
public/assets/32.png
Normal file
|
After Width: | Height: | Size: 223 KiB |
BIN
public/assets/33.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
BIN
public/assets/34.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/35.png
Normal file
|
After Width: | Height: | Size: 226 KiB |
BIN
public/assets/36.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
public/assets/37.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
public/assets/38.png
Normal file
|
After Width: | Height: | Size: 227 KiB |
BIN
public/assets/39.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/assets/4.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
public/assets/40.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/41.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/assets/42.png
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
public/assets/43.png
Normal file
|
After Width: | Height: | Size: 225 KiB |
BIN
public/assets/44.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/assets/45.png
Normal file
|
After Width: | Height: | Size: 655 KiB |
BIN
public/assets/46.png
Normal file
|
After Width: | Height: | Size: 321 KiB |
BIN
public/assets/47.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
public/assets/48.png
Normal file
|
After Width: | Height: | Size: 680 KiB |
BIN
public/assets/49.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
public/assets/5.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
public/assets/6.png
Normal file
|
After Width: | Height: | Size: 353 KiB |
BIN
public/assets/7.png
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
public/assets/8.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
BIN
public/assets/9.png
Normal file
|
After Width: | Height: | Size: 267 KiB |