From d9f0039a5dc959626f873a9c30252153f57750e8 Mon Sep 17 00:00:00 2001 From: Odafe Date: Wed, 15 Nov 2023 09:04:11 +0000 Subject: [PATCH] Build UI - add home page (#19) * setup default ui build * -- * UI: add theme, layouts & first pass at homepage * refactored web3 wallet providers * add theme colors, fixed up sidebar * top navbar styling * wip * added post-card * update homepage * fixed up right sidebar * cleaned up tabs * fix build error --- frontend/nextjs/next.config.js | 12 +- frontend/nextjs/package.json | 6 + .../src/app/dapp/components/providers.tsx | 32 +++ .../src/app/dapp/components/right-sidebar.tsx | 42 +++ .../src/app/dapp/components/sidebar.tsx | 76 ++++++ frontend/nextjs/src/app/dapp/layout.tsx | 83 ++++-- frontend/nextjs/src/app/dapp/page.tsx | 255 +++++++++++++++++- frontend/nextjs/src/app/globals.css | 72 ++++- frontend/nextjs/src/app/layout.tsx | 17 +- frontend/nextjs/src/app/onboarding/layout.tsx | 9 + frontend/nextjs/src/app/onboarding/page.tsx | 9 + frontend/nextjs/src/components/ui/badge.tsx | 36 +++ frontend/nextjs/src/components/ui/button.tsx | 7 +- frontend/nextjs/src/components/ui/card.tsx | 79 ++++++ .../nextjs/src/components/ui/forms/search.tsx | 13 + frontend/nextjs/src/components/ui/input.tsx | 25 ++ .../components/ui/navigation/navigation.tsx | 9 + .../nextjs/src/components/ui/post-card.tsx | 85 ++++++ .../nextjs/src/components/ui/scroll-area.tsx | 48 ++++ .../nextjs/src/components/ui/separator.tsx | 31 +++ frontend/nextjs/src/components/ui/tabs.tsx | 55 ++++ .../src/components/ui/theme-provider.tsx | 9 + frontend/nextjs/tailwind.config.ts | 24 +- 23 files changed, 981 insertions(+), 53 deletions(-) create mode 100644 frontend/nextjs/src/app/dapp/components/providers.tsx create mode 100644 frontend/nextjs/src/app/dapp/components/right-sidebar.tsx create mode 100644 frontend/nextjs/src/app/dapp/components/sidebar.tsx create mode 100644 frontend/nextjs/src/app/onboarding/layout.tsx create mode 100644 frontend/nextjs/src/app/onboarding/page.tsx create mode 100644 frontend/nextjs/src/components/ui/badge.tsx create mode 100644 frontend/nextjs/src/components/ui/card.tsx create mode 100644 frontend/nextjs/src/components/ui/forms/search.tsx create mode 100644 frontend/nextjs/src/components/ui/input.tsx create mode 100644 frontend/nextjs/src/components/ui/navigation/navigation.tsx create mode 100644 frontend/nextjs/src/components/ui/post-card.tsx create mode 100644 frontend/nextjs/src/components/ui/scroll-area.tsx create mode 100644 frontend/nextjs/src/components/ui/separator.tsx create mode 100644 frontend/nextjs/src/components/ui/tabs.tsx create mode 100644 frontend/nextjs/src/components/ui/theme-provider.tsx diff --git a/frontend/nextjs/next.config.js b/frontend/nextjs/next.config.js index 767719f..2a708d8 100644 --- a/frontend/nextjs/next.config.js +++ b/frontend/nextjs/next.config.js @@ -1,4 +1,14 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {} +const nextConfig = { + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'images.unsplash.com', + port: '', + }, + ], + }, +} module.exports = nextConfig diff --git a/frontend/nextjs/package.json b/frontend/nextjs/package.json index 6144711..97f618e 100644 --- a/frontend/nextjs/package.json +++ b/frontend/nextjs/package.json @@ -9,16 +9,22 @@ "lint": "next lint" }, "dependencies": { + "@radix-ui/react-icons": "^1.3.0", + "@radix-ui/react-scroll-area": "^1.0.5", + "@radix-ui/react-separator": "^1.0.3", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.0.4", "@rainbow-me/rainbowkit": "^1.1.4", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "ethers": "^6.8.1", "lucide-react": "^0.291.0", "next": "14.0.1", + "next-themes": "^0.2.1", "prettier": "^3.0.3", "react": "^18", "react-dom": "^18", + "react-icons": "^4.11.0", "tailwind-merge": "^2.0.0", "tailwindcss-animate": "^1.0.7", "viem": "^1.18.1", diff --git a/frontend/nextjs/src/app/dapp/components/providers.tsx b/frontend/nextjs/src/app/dapp/components/providers.tsx new file mode 100644 index 0000000..bc29b8a --- /dev/null +++ b/frontend/nextjs/src/app/dapp/components/providers.tsx @@ -0,0 +1,32 @@ +"use client"; +import React from 'react'; +import '@rainbow-me/rainbowkit/styles.css'; +import { + RainbowKitProvider, + darkTheme +} from '@rainbow-me/rainbowkit'; + +import { emtChains, emtWagmiConfig } from "../../../../emt.config" +import { WagmiConfig } from 'wagmi'; +import { ContractProvider } from '@/lib/hooks/contracts'; + +// Web3 Wallet Connector's Provider +export default function DappProviders({ + children, +}: { + children: React.ReactNode +}) { + return ( + + + + {children} + + + + ) +} diff --git a/frontend/nextjs/src/app/dapp/components/right-sidebar.tsx b/frontend/nextjs/src/app/dapp/components/right-sidebar.tsx new file mode 100644 index 0000000..15b757d --- /dev/null +++ b/frontend/nextjs/src/app/dapp/components/right-sidebar.tsx @@ -0,0 +1,42 @@ +import Link from "next/link" +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { ScrollArea } from "@/components/ui/scroll-area" +import {HiOutlineHome, HiOutlineUser, HiOutlineEnvelope} from 'react-icons/hi2' + +interface SidebarProps extends React.HTMLAttributes { + +} + +const primaryNavigationLinks = [ + { + title: "Home", + icon: HiOutlineHome, + isActive: false, + href: "/dapp" + }, + { + title: "My Profile", + icon: HiOutlineUser, + isActive: false, + href: "/my-profile" + }, + { + title: "Notifications", + icon: HiOutlineEnvelope, + isActive: false, + href: "/notifications" + } +] + +export function RightSidebar({ className, children }: SidebarProps) { + return ( +
+
+
+ {children} +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/nextjs/src/app/dapp/components/sidebar.tsx b/frontend/nextjs/src/app/dapp/components/sidebar.tsx new file mode 100644 index 0000000..5b4e3a1 --- /dev/null +++ b/frontend/nextjs/src/app/dapp/components/sidebar.tsx @@ -0,0 +1,76 @@ +import Link from "next/link" +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" +import { ScrollArea } from "@/components/ui/scroll-area" +import {HiOutlineHome, HiOutlineUser, HiOutlineEnvelope} from 'react-icons/hi2' + +interface SidebarProps extends React.HTMLAttributes { + +} + +const primaryNavigationLinks = [ + { + title: "Home", + icon: HiOutlineHome, + isActive: false, + href: "/dapp" + }, + { + title: "My Profile", + icon: HiOutlineUser, + isActive: false, + href: "/my-profile" + }, + { + title: "Notifications", + icon: HiOutlineEnvelope, + isActive: false, + href: "/notifications" + } +] + +export function Sidebar({ className }: SidebarProps) { + return ( +
+
+
+
+ {primaryNavigationLinks.map((link, key)=> ( + + ))} +
+ +
+
+
+

+ Resources +

+
+ + + + +
+
+ +
+
+
+ ) +} \ No newline at end of file diff --git a/frontend/nextjs/src/app/dapp/layout.tsx b/frontend/nextjs/src/app/dapp/layout.tsx index c61dd42..8e156c3 100644 --- a/frontend/nextjs/src/app/dapp/layout.tsx +++ b/frontend/nextjs/src/app/dapp/layout.tsx @@ -1,34 +1,67 @@ -"use client"; + import React from 'react'; +import { Metadata } from 'next' import '@rainbow-me/rainbowkit/styles.css'; import { - ConnectButton, - RainbowKitProvider, + ConnectButton } from '@rainbow-me/rainbowkit'; +import { Sidebar } from './components/sidebar'; +import { RightSidebar } from './components/right-sidebar'; +import { Search } from '@/components/ui/forms/search'; +import { Button } from '@/components/ui/button'; +import { HiOutlinePencilAlt } from "react-icons/hi" +import DappProviders from './components/providers'; +import { ScrollArea } from "@/components/ui/scroll-area" -import {emtChains, emtWagmiConfig} from "./../../../emt.config" -import { WagmiConfig } from 'wagmi'; -import { ContractProvider } from '@/lib/hooks/contracts'; - - - +export const metadata: Metadata = { + title: 'MEMM! Homepage', +} export default function DappLayout({ - children, - }: { - children: React.ReactNode - }) { - return ( - - - + children +}: { + children: React.ReactNode +}) { + return ( + <> +
- +
+
+

MEMM!

+
+ + + +
+
+
- {children} -
-
-
- - ) - } + +
+
+
+
+ +
+ {children} +
+ +
+
+
+
+ + + ) +} diff --git a/frontend/nextjs/src/app/dapp/page.tsx b/frontend/nextjs/src/app/dapp/page.tsx index 03be6b3..817c298 100644 --- a/frontend/nextjs/src/app/dapp/page.tsx +++ b/frontend/nextjs/src/app/dapp/page.tsx @@ -1,13 +1,133 @@ "use client"; +import React from "react"; import { Button } from "@/components/ui/button"; import { useContracts } from "@/lib/hooks/contracts"; -import React from "react"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import PostCard from "@/components/ui/post-card"; +import { Separator } from "@/components/ui/separator"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { RightSidebar } from "./components/right-sidebar"; +import Image from "next/image"; +import { HiCheckBadge, HiOutlineFire } from "react-icons/hi2" +import { Badge } from "@/components/ui/badge"; +import Link from "next/link"; + +const dummyPosts = [ + { + author: { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true" + }, + post: { + title: "I’m an experienced CEO. I applied for 1001 positions. This is what happened.", + body: "Et pulvinar purus purus pharetra non lobortis nunc. Consectetur feugiat orci consectetur consectetur facilisi. Urna cursus risus nisl sit suscipit nunc sed id in. ", + image: "https://images.unsplash.com/photo-1577100078279-b3445eae827c?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" + }, + metadata: { + upvotes: 435, + downvotes: 23, + permalink: "something.com", + datePublished: "5hrs ago" + } + }, + { + author: { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true" + }, + post: { + title: "I’m an experienced CEO. I applied for 1001 positions. This is what happened.", + body: "Et pulvinar purus purus pharetra non lobortis nunc. Consectetur feugiat orci consectetur consectetur facilisi. Urna cursus risus nisl sit suscipit nunc sed id in. ", + image: "https://images.unsplash.com/photo-1577100078279-b3445eae827c?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" + }, + metadata: { + upvotes: 435, + downvotes: 23, + permalink: "something.com", + datePublished: "5hrs ago" + } + }, + { + author: { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true" + }, + post: { + title: "I’m an experienced CEO. I applied for 1001 positions. This is what happened.", + body: "Et pulvinar purus purus pharetra non lobortis nunc. Consectetur feugiat orci consectetur consectetur facilisi. Urna cursus risus nisl sit suscipit nunc sed id in. ", + image: "https://images.unsplash.com/photo-1577100078279-b3445eae827c?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" + }, + metadata: { + upvotes: 435, + downvotes: 23, + permalink: "something.com", + datePublished: "5hrs ago" + } + }, + { + author: { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true" + }, + post: { + title: "I’m an experienced CEO. I applied for 1001 positions. This is what happened.", + body: "Et pulvinar purus purus pharetra non lobortis nunc. Consectetur feugiat orci consectetur consectetur facilisi. Urna cursus risus nisl sit suscipit nunc sed id in. ", + image: "https://images.unsplash.com/photo-1577100078279-b3445eae827c?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" + }, + metadata: { + upvotes: 435, + downvotes: 23, + permalink: "something.com", + datePublished: "5hrs ago" + } + }, +] + +const topCreatorList = [ + { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "false", + skill: "UI Design", + href: "/profile/naval", + ment: 134 + }, + { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true", + skill: "Java", + href: "/profile/naval", + ment: 693 + }, + { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true", + skill: "Ruby", + href: "/profile/naval", + ment: 953 + }, + { + name: "Naval", + avatar: "https://images.unsplash.com/photo-1607746882042-944635dfe10e?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTB8fGF2YXRhcnxlbnwwfHwwfHx8MA%3D%3D", + mentor: "true", + skill: "AI", + href: "/profile/naval", + ment: 422 + }, +] + export default function RootLayout() { const { EMTMarketPlace, ExpertToken, MentorToken } = useContracts(); async function handleEMTMarketPlace() { - const val = await EMTMarketPlace._DOWNVOTE_WEIGHT(); - alert(val); + const val = await EMTMarketPlace.downVoteWeight(); + alert(val); } async function handleExpertToken() { @@ -20,11 +140,132 @@ export default function RootLayout() { alert(val); } + // return ( + //
+ // + // + // + //
+ // ); + return ( -
- - - +
+
+ +
+ + + Following + Design + + +
+ {dummyPosts.map((post, key) => { + return <> + + + + })} +
+
+ +
+ {dummyPosts.map((post, key) => { + return <> + + + + })} +
+
+
+
+
+
+ + <> + +
+

+ Top Creators +

+
+ {topCreatorList.map((profile, key) => { + return +
+
+ {`${profile.name}-avatar`} +
+
+
+

{profile.name}

+ {profile.mentor === "true" && } +
+ {profile.skill} +
+
+
+ +
+ 245 MENT +
+
+ + })} + + +
+
+ +
+

+ Who to Follow +

+
+ {topCreatorList.map((profile, key) => { + return +
+
+ {`${profile.name}-avatar`} +
+
+
+

{profile.name}

+ {profile.mentor === "true" && } +
+ {profile.skill} +
+
+
+ +
+ 245 MENT +
+
+ + })} + + +
+
+ +
+ + ); } diff --git a/frontend/nextjs/src/app/globals.css b/frontend/nextjs/src/app/globals.css index 6a75725..deb2264 100644 --- a/frontend/nextjs/src/app/globals.css +++ b/frontend/nextjs/src/app/globals.css @@ -3,7 +3,9 @@ @tailwind utilities; @layer base { - :root { + + + /* :root { --background: 0 0% 100%; --foreground: 222.2 84% 4.9%; @@ -28,14 +30,14 @@ --destructive: 0 84.2% 60.2%; --destructive-foreground: 210 40% 98%; - --border: 214.3 31.8% 91.4%; + --stroke: 0, 0%, 98%, 0.1; --input: 214.3 31.8% 91.4%; --ring: 222.2 84% 4.9%; --radius: 0.5rem; - } + } */ - .dark { + /* .dark { --background: 222.2 84% 4.9%; --foreground: 210 40% 98%; @@ -63,6 +65,68 @@ --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 212.7 26.8% 83.9%; + } */ + + :root { + --primary-black: 0deg 0% 0%; + --white: 0deg 0% 100%; + --primary-white: 0deg 0% 100%; + + --accent-shade: 222deg 46% 17%; + --accent-1: 222deg 47% 11%; + --accent-2: 241deg 77% 63%; + --accent-3: 330deg 81% 60%; + --accent-4: 0deg 91% 71%; + + --white: 0deg 0% 100%; + --text: 226deg 100% 94%; + --text-alt: 230deg 39% 68%; + --text-muted: 226deg 22% 73%; + + --stroke: 0deg 0% 98%; + + --gray-50: 0deg 0% 98%; + --gray-100: 220deg 20% 97%; + --gray-200: 216deg 11% 91%; + --gray-300: 210deg 9% 82%; + --gray-400: 212deg 8% 65%; + --gray-700: 208deg 9% 30%; + --gray-600: 208deg 7% 37%; + --gray-500: 212deg 7% 43%; + --gray-800: 208deg 10% 25%; + --gray-900: 210deg 12% 16%; + --gray-1000: 210deg 12% 16%; + + --radius: 0.5rem; + } + + .dark { + --primary-black: 0deg 0% 0%; + --primary-white: 0deg 0% 100%; + + --accent-shade: 222deg 46% 17%; + --accent-1: 222deg 47% 11%; + --accent-2: 241deg 77% 63%; + --accent-3: 330deg 81% 60%; + --accent-4: 0deg 91% 71%; + + --text: 226deg 100% 94%; + --text-alt: 230deg 39% 68%; + --text-muted: 226deg 22% 73%; + + --stroke: 0deg 0% 98%; + + --gray-50: 0deg 0% 98%; + --gray-100: 220deg 20% 97%; + --gray-200: 216deg 11% 91%; + --gray-300: 210deg 9% 82%; + --gray-400: 212deg 8% 65%; + --gray-700: 208deg 9% 30%; + --gray-600: 208deg 7% 37%; + --gray-500: 212deg 7% 43%; + --gray-800: 208deg 10% 25%; + --gray-900: 210deg 12% 16%; + --gray-1000: 210deg 12% 16%; } } diff --git a/frontend/nextjs/src/app/layout.tsx b/frontend/nextjs/src/app/layout.tsx index e02eb35..fe8bc40 100644 --- a/frontend/nextjs/src/app/layout.tsx +++ b/frontend/nextjs/src/app/layout.tsx @@ -1,13 +1,13 @@ import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' - +import { ThemeProvider } from '@/components/ui/theme-provider' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { - title: 'Create Next App', - description: 'Generated by create next app', + title: 'MEMM!', + description: 'Mentorship from the best', } export default function RootLayout({ @@ -18,7 +18,16 @@ export default function RootLayout({ return ( - {children} + + + {children} + + ) diff --git a/frontend/nextjs/src/app/onboarding/layout.tsx b/frontend/nextjs/src/app/onboarding/layout.tsx new file mode 100644 index 0000000..e34dd06 --- /dev/null +++ b/frontend/nextjs/src/app/onboarding/layout.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const OnboardingLayout = () => { + return ( +
OnboardingLayout
+ ) +} + +export default OnboardingLayout \ No newline at end of file diff --git a/frontend/nextjs/src/app/onboarding/page.tsx b/frontend/nextjs/src/app/onboarding/page.tsx new file mode 100644 index 0000000..e8b5644 --- /dev/null +++ b/frontend/nextjs/src/app/onboarding/page.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const OnboardingPage = () => { + return ( +
OnboardingPage
+ ) +} + +export default OnboardingPage \ No newline at end of file diff --git a/frontend/nextjs/src/components/ui/badge.tsx b/frontend/nextjs/src/components/ui/badge.tsx new file mode 100644 index 0000000..46f9936 --- /dev/null +++ b/frontend/nextjs/src/components/ui/badge.tsx @@ -0,0 +1,36 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const badgeVariants = cva( + "inline-flex items-center rounded-full border px-1.5 py-0.1 text-[11px] font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-accent-2 text-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-accent-shade text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +export interface BadgeProps + extends React.HTMLAttributes, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/frontend/nextjs/src/components/ui/button.tsx b/frontend/nextjs/src/components/ui/button.tsx index 0ba4277..6d67f86 100644 --- a/frontend/nextjs/src/components/ui/button.tsx +++ b/frontend/nextjs/src/components/ui/button.tsx @@ -5,10 +5,11 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const buttonVariants = cva( - "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", + "inline-flex items-center justify-center whitespace-nowrap rounded-full text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", { variants: { variant: { + gradient: "bg-pink-gradient hover:bg-reverse-pink-gradient hover:text-white/80", default: "bg-primary text-primary-foreground hover:bg-primary/90", destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90", @@ -16,8 +17,8 @@ const buttonVariants = cva( "border border-input bg-background hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", + ghost: "hover:bg-accent-shade hover:text-accent-foreground", + link: "text-foreground underline-offset-4 hover:underline", }, size: { default: "h-10 px-4 py-2", diff --git a/frontend/nextjs/src/components/ui/card.tsx b/frontend/nextjs/src/components/ui/card.tsx new file mode 100644 index 0000000..afa13ec --- /dev/null +++ b/frontend/nextjs/src/components/ui/card.tsx @@ -0,0 +1,79 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +

+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/frontend/nextjs/src/components/ui/forms/search.tsx b/frontend/nextjs/src/components/ui/forms/search.tsx new file mode 100644 index 0000000..6906e7f --- /dev/null +++ b/frontend/nextjs/src/components/ui/forms/search.tsx @@ -0,0 +1,13 @@ +import { Input } from "@/components/ui/input" + +export function Search() { + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/frontend/nextjs/src/components/ui/input.tsx b/frontend/nextjs/src/components/ui/input.tsx new file mode 100644 index 0000000..677d05f --- /dev/null +++ b/frontend/nextjs/src/components/ui/input.tsx @@ -0,0 +1,25 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/frontend/nextjs/src/components/ui/navigation/navigation.tsx b/frontend/nextjs/src/components/ui/navigation/navigation.tsx new file mode 100644 index 0000000..44b702f --- /dev/null +++ b/frontend/nextjs/src/components/ui/navigation/navigation.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const Navigation = () => { + return ( +
Navigation
+ ) +} + +export default Navigation \ No newline at end of file diff --git a/frontend/nextjs/src/components/ui/post-card.tsx b/frontend/nextjs/src/components/ui/post-card.tsx new file mode 100644 index 0000000..c8da2ad --- /dev/null +++ b/frontend/nextjs/src/components/ui/post-card.tsx @@ -0,0 +1,85 @@ +import React from 'react' +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card" +import Image from 'next/image' +import Link from 'next/link'; +import { HiCheckBadge, HiOutlineHandThumbUp, HiOutlineHandThumbDown, HiOutlineShare } from "react-icons/hi2"; +import { Button } from '@/components/ui/button'; + + +const PostCard = ({data}: any) => { + const {post, author, metadata} = data + + return ( + + + +
+
+ {`${author.name}-avatar`} +
+
+
+

{author.name}

+ {author.mentor === "true" && } +
+ +
+
+ +
+ + {post.title} + {post.body} +
+ {`${post.title} +
+
+ +
+
+ +
+ {metadata.upvotes} +
+ +
+
+ +
+
+ + +
+
+ + + ) +} + +export default PostCard \ No newline at end of file diff --git a/frontend/nextjs/src/components/ui/scroll-area.tsx b/frontend/nextjs/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..0b4a48d --- /dev/null +++ b/frontend/nextjs/src/components/ui/scroll-area.tsx @@ -0,0 +1,48 @@ +"use client" + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/frontend/nextjs/src/components/ui/separator.tsx b/frontend/nextjs/src/components/ui/separator.tsx new file mode 100644 index 0000000..12d81c4 --- /dev/null +++ b/frontend/nextjs/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/frontend/nextjs/src/components/ui/tabs.tsx b/frontend/nextjs/src/components/ui/tabs.tsx new file mode 100644 index 0000000..02bd208 --- /dev/null +++ b/frontend/nextjs/src/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client" + +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/frontend/nextjs/src/components/ui/theme-provider.tsx b/frontend/nextjs/src/components/ui/theme-provider.tsx new file mode 100644 index 0000000..4203e6a --- /dev/null +++ b/frontend/nextjs/src/components/ui/theme-provider.tsx @@ -0,0 +1,9 @@ +"use client" + +import * as React from "react" +import { ThemeProvider as NextThemesProvider } from "next-themes" +import { type ThemeProviderProps } from "next-themes/dist/types" + +export function ThemeProvider({ children, ...props }: ThemeProviderProps) { + return {children} +} \ No newline at end of file diff --git a/frontend/nextjs/tailwind.config.ts b/frontend/nextjs/tailwind.config.ts index 6d12b64..2879920 100644 --- a/frontend/nextjs/tailwind.config.ts +++ b/frontend/nextjs/tailwind.config.ts @@ -22,13 +22,23 @@ const config: Config = { 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + 'pink-gradient': 'linear-gradient(96deg, hsl(var(--accent-3)) 0%, hsl(var(--accent-4)) 137%)', + 'reverse-pink-gradient': 'linear-gradient(96deg, hsl(var(--accent-4)) 0%, hsl(var(--accent-3)) 137%)', }, colors: { - border: "hsl(var(--border))", - input: "hsl(var(--input))", - ring: "hsl(var(--ring))", - background: "hsl(var(--background))", - foreground: "hsl(var(--foreground))", + border: "hsl(var(--stroke) / 0.1)", + 'alt-stroke': "hsl(var(--stroke) / 0.05)", + input: "hsl(var(--accent-shade))", + ring: "hsl(var(--stroke) / 0.1)", + background: "hsl(var(--accent-1))", + foreground: "hsl(var(--text))", + 'alt': "hsl(var(--text-alt))", + 'muted': "hsl(var(--text-muted))", + 'accent-shade': 'hsl(var(--accent-shade))', + 'accent-1': 'hsl(var(--accent-1))', + 'accent-2': 'hsl(var(--accent-2))', + 'accent-3': 'hsl(var(--accent-3))', + 'accent-4': 'hsl(var(--accent-4))', primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))", @@ -41,10 +51,6 @@ const config: Config = { DEFAULT: "hsl(var(--destructive))", foreground: "hsl(var(--destructive-foreground))", }, - muted: { - DEFAULT: "hsl(var(--muted))", - foreground: "hsl(var(--muted-foreground))", - }, accent: { DEFAULT: "hsl(var(--accent))", foreground: "hsl(var(--accent-foreground))",