Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build UI #22

Merged
merged 18 commits into from
Nov 16, 2023
12 changes: 11 additions & 1 deletion frontend/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,21 @@
},
"dependencies": {
"@auth/firebase-adapter": "^1.0.4",
"@hookform/resolvers": "^3.3.2",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@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",
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-toggle": "^1.0.3",
"@rainbow-me/rainbowkit": "^1.1.4",
"@rainbow-me/rainbowkit-siwe-next-auth": "^0.3.2",
"@tiptap/extension-placeholder": "^2.1.12",
"@tiptap/pm": "^2.1.12",
"@tiptap/react": "^2.1.12",
"@tiptap/starter-kit": "^2.1.12",
"axios": "^1.6.2",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
Expand All @@ -30,12 +38,14 @@
"prettier": "^3.0.3",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.48.2",
"react-icons": "^4.11.0",
"siwe": "^2.1.4",
"tailwind-merge": "^2.0.0",
"tailwindcss-animate": "^1.0.7",
"viem": "^1.18.1",
"wagmi": "^1.4.5"
"wagmi": "^1.4.5",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/node": "^20",
Expand Down
14 changes: 8 additions & 6 deletions frontend/nextjs/src/app/dapp/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@ import '@rainbow-me/rainbowkit/styles.css';
import {
ConnectButton
} from '@rainbow-me/rainbowkit';
import { Sidebar } from './components/sidebar';
import { RightSidebar } from './components/right-sidebar';
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 DappProviders from './_components/providers';
import SessionProvider from "@/lib/hooks/sessionProvider";
import { getServerSession } from "next-auth";
export const metadata: Metadata = {
title: 'MEMM! Homepage',
}

type Props = {
children: React.ReactNode
}

export default async function DappLayout({
children
}: {
children: React.ReactNode
}) {
}: Props) {
const session = await getServerSession();
return (
<>
Expand Down
221 changes: 221 additions & 0 deletions frontend/nextjs/src/app/dapp/p/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import React from 'react'
import { HiCheckBadge, HiOutlineHandThumbUp, HiOutlineHandThumbDown, HiOutlineShare, HiOutlineFire } from 'react-icons/hi2'
import Image from 'next/image'
import Link from 'next/link'
import { Button } from '@/components/ui/button'
import { Card, CardHeader, CardContent, CardTitle, CardDescription, CardFooter } from '@/components/ui/card'
import { Separator } from '@/components/ui/separator'
import { Badge } from '@/components/ui/badge'
import { ScrollArea } from '@/components/ui/scroll-area'
import { RightSidebar } from '../../_components/right-sidebar'

const Post = ({ params }: { params: { slug: string } }) => {
const post = {
title: "I’m an experienced CEO. I applied for 1001 positions. This is what happened.",
body: `Facilisi at lorem semper eget. Eget posuere dictumst velit lacus est. Fringilla quam sollicitudin diam sollicitudin magna. Arcu ullamcorper nisl at aliquet luctus. Vitae commodo dictum sed et. In ultrices eu curabitur neque pulvinar ac eget ullamcorper lorem. Velit vitae id sit gravida mi viverra. Non ipsum nunc sed risus fermentum sed in. Lectus donec dignissim diam sed non tortor. Nibh euismod id tincidunt scelerisque cras est. Tincidunt mollis commodo urna scelerisque nibh at sed. Amet odio erat congue diam in.

Elit tellus velit diam suspendisse eget. Sed in et accumsan amet id sed ultrices lorem mollis. Donec tempus sapien pellentesque est pretium et. Ut euismod vitae feugiat donec amet euismod arcu egestas dis. Elementum neque suspendisse facilisis mi ullamcorper purus aliquam adipiscing. Sagittis non tristique sed sed purus magna sem. Integer non habitasse ornare in amet mauris id. Nulla condimentum ipsum aliquam urna vitae consequat. Nec lobortis aenean auctor imperdiet facilisis vel. Cras amet euismod neque dictumst vestibulum. Faucibus orci accumsan ipsum eget nunc magnis elit. Quam ultricies turpis scelerisque aliquet amet enim venenatis non. Iaculis hac in aliquet sed blandit vestibulum etiam. Adipiscing adipiscing augue senectus tempor. Mauris pellentesque consequat aliquet sagittis.

In diam vestibulum eu tellus suspendisse non vestibulum. Ut ipsum risus suscipit amet quam a mi. Pellentesque est in amet in. Vitae urna laoreet non eu. Euismod ut quis elit risus massa. Posuere amet massa pulvinar cursus morbi nibh varius quam proin. Et tortor risus elementum morbi ante tortor adipiscing pretium vestibulum.`,
image: "https://images.unsplash.com/photo-1559136555-9303baea8ebd?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
author: {
name: "Naval",
avatar: "https://images.unsplash.com/photo-1640960543409-dbe56ccc30e2?q=80&w=1480&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
mentor: "true"
},
metadata: {
upvotes: 314,
downvotes: 42
}
}

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
},
]

return (
<div className="grid grid-cols-1 md:grid-cols-6 col-span-4">
<div className="h-full px-4 py-6 lg:px-6 col-span-1 md:col-span-4 md:border-x">
<ScrollArea className="h-[90vh] w-full">
<Card className='border-none'>
<CardHeader className='px-0 pt-0'>
<div className='flex items-center'>
<div className="w-10 h-10 relative">
<Image
fill
className='rounded-full object-cover'
loading="eager"
src={post.author.avatar}
alt={`${post.author.name}-avatar`}
quality={80}
/>
</div>
<div className='ml-3'>
<div className="flex items-center">
<p className='text-md text-foreground'>{post.author.name}</p>
{post.author.mentor === "true" && <HiCheckBadge className="w-4 h-4 ml-1 text-accent-3" />}
<div className='ml-2 text-[11px] text-muted'>20 secs. ago</div>
</div>
<Button variant="ghost" className='text-xs px-0 py-0 rounded-sm h-auto hover:bg-transparent hover:text-accent-3 text-muted'>Follow</Button>
</div>
</div>

</CardHeader>
<CardContent className='space-y-5 px-0'>
<div className="w-full h-[400px] relative">
<Image
fill
src={post.image}
className='rounded-md object-cover'
loading="lazy"
alt={`${post.title} cover photo`}
/>
</div>
<CardTitle className='font-bold text-3xl text-foreground tracking-wide'>{post.title}</CardTitle>
<CardDescription className='text-muted text-sm'>{post.body}</CardDescription>
</CardContent>
<Separator className="bg-border mb-3" />
<CardFooter className='pb-0 px-0 flex justify-between'>

<div className='flex items-center'>
<div className="flex items-center">
<Button variant="ghost" aria-label='Upvote a post' size="icon">
<HiOutlineHandThumbUp className="h-5 w-5 text-foreground" />
</Button>
<div className='text-sm text-foreground ml-1'>
{post.metadata.upvotes}
</div>

</div>
<div className="flex items-center ml-2">
<Button variant="ghost" aria-label='Upvote a post' size="icon">
<HiOutlineHandThumbDown className="h-5 w-5 text-foreground" />
</Button>
</div>
</div>

<Button variant="ghost" aria-label='Upvote a post' size="icon">
<HiOutlineShare className="h-5 w-5 text-foreground" />
</Button>
</CardFooter>
</Card>
</ScrollArea>
</div>
<RightSidebar className="hidden md:block min-h-[94vh] col-span-2 lg:col-span-2" >
<>

<div className="mb-8">
<h2 className="mb-1 text-md pl-3 font-semibold tracking-tight">
Top Creators
</h2>
<div className="flex flex-col gap-y-0">
{topCreatorList.map((profile, key) => {
return <Link href={profile.href} key={`top-creator-${key}`} className="px-3 py-2 rounded-md flex w-full items-center justify-between hover:bg-accent-shade">
<div className='flex items-center'>
<div className="w-10 h-10 relative">
<Image
fill
className='rounded-full object-cover'
loading="eager"
src={profile.avatar}
alt={`${profile.name}-avatar`}
quality={80}
/>
</div>
<div className='ml-3'>
<div className="flex items-center">
<p className='text-md text-foreground'>{profile.name}</p>
{profile.mentor === "true" && <HiCheckBadge className="w-4 h-4 ml-1 text-accent-3" />}
</div>
<Badge>{profile.skill}</Badge>
</div>
</div>
<div className="flex items-center text-xs text-muted">
<HiOutlineFire className="w-4 h-4 ml-1 text-muted" />
<div className="ml-1">
245 MENT
</div>
</div>
</Link>
})}


</div>
</div>

<div className="">
<h2 className="mb-1 text-md pl-3 font-semibold tracking-tight">
Who to Follow
</h2>
<div className="flex flex-col gap-y-0">
{topCreatorList.map((profile, key) => {
return <Link href={profile.href} key={`top-creator-${key}`} className="px-3 py-2 rounded-md flex w-full items-center justify-between hover:bg-accent-shade">
<div className='flex items-center'>
<div className="w-10 h-10 relative">
<Image
fill
className='rounded-full object-cover'
loading="eager"
src={profile.avatar}
alt={`${profile.name}-avatar`}
quality={80}
/>
</div>
<div className='ml-3'>
<div className="flex items-center">
<p className='text-md text-foreground'>{profile.name}</p>
{profile.mentor === "true" && <HiCheckBadge className="w-4 h-4 ml-1 text-accent-3" />}
</div>
<Badge>{profile.skill}</Badge>
</div>
</div>
<div className="flex items-center text-xs text-muted">
<HiOutlineFire className="w-4 h-4 ml-1 text-muted" />
<div className="ml-1">
245 MENT
</div>
</div>
</Link>
})}


</div>
</div>
</>
</RightSidebar>
</div>
)
}

export default Post
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client"
import React from 'react'
import * as z from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"

import { Button } from "@/components/ui/button"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { useToast } from "@/components/ui/use-toast"
import { Textarea } from "@/components/ui/textarea"
import RichTextEditor from '@/components/ui/rich-text-editor'

const formSchema = z.object({
postTitle: z.string().min(1, {
message: "Title can't be empty",
}),
postBody: z.string()
})

const CreatePostForm = () => {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
postTitle: "",
postBody: "",
},
})
const { toast } = useToast()

function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
toast({
description: "Your post has been created",

})
}

return (
<div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="postTitle"
render={({ field }) => (
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input placeholder="Your post title" {...field} />
</FormControl>
<FormMessage className='text-xs text-muted font-normal' />
</FormItem>
)}
/>

<FormField
control={form.control}
name="postBody"
render={({ field }) => (
<FormItem>
<FormLabel>Body</FormLabel>
<FormControl>
<RichTextEditor placeholder="Answer a question or explain a concept" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="flex justify-end w-full">
<Button type="submit" variant='gradient' className='w-[160px] '>Post</Button>
</div>
</form>
</Form>
</div>
)
}

export default CreatePostForm
Loading
Loading