Skip to content

Commit

Permalink
v0.3 (#26)
Browse files Browse the repository at this point in the history
* add hover effect to toolbar button

* implement new color scheme and layout

* landing page background image doesn't scroll anymore

* fix: add group routes to handle stateful / stateless toolbar layouts

* feat: create landing page and force redirect from root route to landing

* feat: responsive layout

* feat: Show site loading in toolbar

* fix: Stop background image on landing page from expanding height of container

* fix: resolve build errors due to incorrect image paths

* fix: Remove lint warnings

* fix: change discover page props to format supported by next13

* feat: 🚧 [WIP] Convert landing page from image

* chore: 🚧 Add ethereum icon + update responsive styles

* chore: 📦 Add `framer-motion`

* feat: ✨ Add countdown timer to landing page

* feat: Basic navigation menu implemented for v0.3

* feat: Add signed-in options to menu

* fix: close menu on route navigation

* feat: Add border to navigation menu

* style: Run lint

* refactor: Remove duplicate gradient

* refactor: 📱 Update responsive design for timer and splash screen

* refactor: 📱 Update responsive styles for splash screen

* refactor: 💫 Timer animation will now pause on each number

* refactor: 💫 Update easing function of timer animation

* feat: Initial wallet context set up to support web3Auth

* refactor: Import links for main menu from siteConfig instead of hardcoding in menu file

* feat: update menu with new links

* feat: Add menu open/close animation

* fix: Remove pointer events from menu while closed

* fix: Clean up mobile designs for navigation menu

* refactor: Lint code

* feat: Web3 auth login status renders necessary links in navigation menu and persists on page refresh

* feat: 🔨 Add function to create proxy urls for mix

* refactor: ♻️ Add proxyUrl to C4Content type and use it in Discover to display websites

* refactor: ♻️ update `fetchMix` to `createProxyUrls` and return the mix with `proxyUrls` added

* fix: 🏷️ Add missing type for `createProxyUrls` fn

* feat: Web3 auth login working with updated server

* fix: Shrink menu size for smaller screens

* fix: Change menu options from title case to sentence case

* fix: Change sign up / sign in to sentence case

* feat: ZeroDev integration

* fix: Change custom green color name to avoid overwriting tailwind default

* fix: Change custom green color name to avoid overwriting tailwind default

* refactor: Rename WalletProvider to AuthProvider

* refactor: fix lint warnings

* fix: Comment out old navs to allow site to successfully build

* feat: Initial site details skeleton

* feat: Change xs and sm breakpoints to md

* feat: Site details implemented

* fix: Stop flex shrink on close icon and add gaps betweem sections of site details

* fix: Remove zero dev since it breaks build

* feat: Save progress with signer web3 auth signer being passed around app now

* feat: Fix site details resizing and remove padding from discover page content

* feat: Hide other toolbar popup if one is already open

* feat: Like icon filled in when site is liked

* fix: User likes now load in when a user signs into the site

* feat: Saving progress. Bug exists where duplicate sites are being fetched within mix

* fix: Remove 'ecoding not found' warning stack trace

* feat: Wireframe set up for submit website redesign

* fix: Prevent user likes from being fetched with undefined id

* fix: Fix mix index bug

* feat: Add like button popover. Set text to 14px because it fixs screen better

* refactor: Resolve lint warnings

* password(feat): change usePassword by useJWT and make it persistent

* like(feat): send data in req.body to backend

* likes(fix): remove unused code

* tags(feat): send params in req.body

* url(feat): send params in req.body

* toolbar(fix): spelling

* auth(feat): userId is fetch from jwt

* receipts(feat): save submitUrl, submitTag and like receipts

* feat: Select component almost implemented. Slider almost completed but with a few bugs

* fix: 🐛 Fix nested button issue and conflicting condition in toolbar

* feat: 💫 Add animations and transitions to toolbar

Menu icon popup and glow, Next button nudge

* feat: Correct text line height to reflect figma design

* iframe url debouncing working

* feat: Slider messaging and functionality complete

* feat: Info icon popover added

* feat: Select component add and remove props added

* feat: Not sure what I just added

* feat: Basic styles and browse page layout implemented

* refactor: Resolve lint warnings

* feat: Add proper toolbar labeling based on route

* feat: Background image set for submit website page

* feat: save

* likes(fix): typescript fix (no like parameter)

* likes(fix): popup when you are not logged in. Like otherwise

* fix: Clean up messes related to styling

* refactor: Resolve lint warnings

* feat: initial dashboard design set up

* feat: Tags fed in from server and header on browse page made sticky

* feat: Merge in feat/submit-website

* feat: need to filter by tag on discover page

* feat: Add useEffect

* feat: Mobile design implemented for submit website

* fix: Fix overflow bugs on mobile view

* refactor: Resolve lint warnings and move inline styles for slider into tailwind class

* feat: Clean up RequireAuth component, add loading state, and allow signin via web3auth through it

* refactor: Remove jwt store variables in require auth and replace with signedIn from AuthContext

* chore: 📦 Update pnpm version

* fix: ♿ Add `iframe` title

* feat: Discover page now filters videos based on tag query param

* fix: Filter tags that have no uses

* feat: Mobile designs cleaned up

* feat: Disable cache on browse page

* refactor: Resolve lint warnings

* feat: Displaying user like count, submitted urls, and date of account creation on dashboard

* feat: Show provider used to log in and the associated email with the provider should one exist

* feat: Update navigation menu to get rid of unused routes

* refactor: Resolve lint warnings

* feat: Shrink down text label sizes and decrease margins

* feat: Add error messaging for all text inputs

* fix: Selected tags in select box now overflow and scroll correctly

* refactor: Resolve lint warnings

* fix: Disable slider when creating new tag

* fix: Get frontend to build correctly so netlify preview works

* Update app/(discover)/discover/utils.ts

Co-authored-by: Y6NDR <[email protected]>

* Update app/(stateless-toolbar)/submit-url/components/slider.tsx

Co-authored-by: Y6NDR <[email protected]>

* refactor: Remove mongo generated variable for website count and instead derive it from length of the url array

* fix: Rename error prop in slider to hasError across component

* refactor: Rename duplicate tag state variable on submit url page

* refactor: Remove unsused imports for TagMap

* fix: Center loading text in require auth component

* feat: Change primary button color to a channel4-like green. Update social login order

* fix: Correct browse page scroll

* feat: Landing page transitions to discover at the end of timer countdown

* fix: Change height of main content wrapper to not cause scroll on mobile

* fix: Change content height unit from svh to dvh

* fix: Try adding dvh to height of root layout

* fix: Change h-screen to 100dvh

* fix: Clean up landing page styles to look good on mobile

* feat: Make website url inptut format clearer

* feat: Add error highlightin invalid url input on the frontend

* fix: Resolve lint warnings and resolve typescript error to allow site to build

---------

Co-authored-by: thebeyondr <[email protected]>
Co-authored-by: Nico Serrano <[email protected]>
Co-authored-by: Nico Serrano <[email protected]>
  • Loading branch information
4 people authored Jan 15, 2024
1 parent af54fa5 commit b510154
Show file tree
Hide file tree
Showing 62 changed files with 5,108 additions and 952 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
API_URL='http://localhost:8000/api'
NEXT_PUBLIC_WEB3_AUTH_CLIENT_ID=''
NEXT_PUBLIC_API_URL='http://localhost:8000/api'
NEXT_PUBLIC_API_LOGIN_SECRET="login to backend"
NEXT_PUBLIC_RPC_URL='https://sepolia.infura.io/v3/<YOUR_INFURA_KEY>'
Expand Down
26 changes: 26 additions & 0 deletions app/(discover)/discover/SiteFrame.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"use client"

import React from "react"
import { C4Content } from "@/types"

interface SiteFrameProps {
site: C4Content | null
}

const SiteFrame: React.FC<SiteFrameProps> = ({ site }) => {
if (!site) return null

return (
<section className="h-full rounded-2xl">
<div className="relative flex h-full w-full items-center justify-center overflow-hidden rounded-xl bg-secondary">
<iframe
src={site.proxyUrl}
title={site.title}
className="h-full w-full"
/>
</div>
</section>
)
}

export default SiteFrame
57 changes: 57 additions & 0 deletions app/(discover)/discover/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client"

import Link from "next/link"
import { C4Content } from "@/types"

import { Button } from "@/components/ui/button"

import SiteFrame from "./SiteFrame"
import { feedbackMessages } from "./utils"

interface DiscoverPageProps {
params: {
currentSite: C4Content | null
error: {
message: string
}
isLoading: boolean
}
}

const Discover = ({
params: { currentSite, error, isLoading },
}: DiscoverPageProps) => {
if (error.message !== "") {
return (
<div className="flex h-full w-full flex-col items-center justify-center space-y-3 p-6">
<p className="text-lg">{feedbackMessages["not-found"]}</p>
<Link href="/browse" passHref>
<Button variant="default" size="lg">
Back to Browse
</Button>
</Link>
</div>
)
}
if (isLoading) {
return (
<div className="flex h-full items-center justify-center">
<p className="mx-auto flex w-full items-center justify-center p-6">
{feedbackMessages.loading}
</p>
</div>
)
}

return (
!isLoading &&
!error.message &&
currentSite && (
<section className="h-full">
<SiteFrame site={currentSite} />
</section>
)
)
}

export default Discover
79 changes: 79 additions & 0 deletions app/(discover)/discover/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { createProxyUrls } from "@/app/utils"

export const fetchMix = async (tags: string[], limit: number) => {
const mixParams = createMixParams(tags, limit)
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/mix?${mixParams.toString()}`
)
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`)
}
const data = await response.json()
const mixWithProxyUrls = createProxyUrls(data.urls)
return { urls: mixWithProxyUrls }
} catch (error) {
let message = "Unknown error"
if (error instanceof Error) message = error.message
console.error("Error fetching mix:", error)
return { message }
}
}

export const fetchLikes = async (userId: string) => {
try {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/likes/${userId}`
)
if (!response.ok) {
throw new Error(`Request failed with status ${response.status}`)
}
const { likes } = await response.json()
return likes.map(({ id }: { id: string }) => id)
} catch (error) {
let message = "Unknown error"
if (error instanceof Error) message = error.message
console.error("Error fetching mix:", error)
return { message }
}
}

export const updateLikesInApi = async (
contentId: string,
liked: boolean,
token: string,
updateList: (data: any) => void
) => {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/like/${contentId}`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
liked: liked,
}),
}
).then((res) => res.json())
updateList({
object: response.like,
type: "like",
receipt: response.receipt,
})
}

export const feedbackMessages = {
"not-found":
"Oops! We couldn't find any content with these tags... Try using a different one",
loading: "Loading content...",
}

export const createMixParams = (tags: string[], mixLimit: number) => {
const mixParams = new URLSearchParams()
tags.forEach((tag) => mixParams.append("tags", tag))
mixParams.append("limit", mixLimit.toString())

return mixParams
}
31 changes: 31 additions & 0 deletions app/(discover)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use client"

import MainContentWrapper from "@/components/main-content-wrapper"
import Toolbar from "@/components/toolbar"
import useMix from "@/app/hooks/useMix"

import Discover from "./discover/page"

export default function DiscoverLayout({
children,
}: {
children: React.ReactNode
}) {
const { changeSite, currentSite, error, isLoading, likeOrUnlike, userLikes } =
useMix()

return (
<>
<MainContentWrapper>
<Discover params={{ currentSite, error, isLoading }} />
</MainContentWrapper>
<Toolbar
changeSite={changeSite}
currentSite={currentSite}
isLoading={isLoading}
likeOrUnlike={likeOrUnlike}
userLikes={userLikes}
/>
</>
)
}
50 changes: 50 additions & 0 deletions app/(stateless-toolbar)/browse/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Link from "next/link"
import { Tag } from "@/types"

import { random } from "@/app/utils"

const fetchTags = async () => {
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/tag`, {
cache: "no-store",
})
const { tags } = await res.json()
return tags as Tag[]
}

const Browse = async () => {
const tags = await fetchTags()
return (
<div className="flex h-full flex-col">
<div className="sticky top-0 z-10 bg-shark-950 p-4 md:p-10">
<div className="w-fit bg-c4-gradient-green bg-clip-text text-[56px] font-extrabold leading-none text-transparent">
Topics
</div>
<div className="mt-2 text-lg text-shark-50">
Your channel guides for various topics. Select one of following &
let’s start watching
</div>
</div>
<div className="grow overflow-y-auto">
{tags
.filter(({ urls }) => !!urls.length)
.map(({ name, urls }) => (
<Link
className="relative flex cursor-pointer items-center justify-between gap-6 border-y border-shark-500 px-10 py-4 hover:border-c4-green"
href={`discover?tag=${name}`}
>
<div className="truncate text-xl text-shark-50">{name}</div>
<div
className="absolute z-[-1] h-full w-px bg-c4-green"
style={{
left: `${random(25, 89)}%`,
}}
/>
<div className="text-xl text-c4-green">{urls.length}</div>
</Link>
))}
</div>
</div>
)
}

export default Browse
75 changes: 75 additions & 0 deletions app/(stateless-toolbar)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"use client"

import { useEffect, useState } from "react"
import { useAuth } from "@/contexts/AuthContext"
import { useJwtStore } from "@/store/jwt"
import moment from "moment"

import RequireAuth from "@/components/helper/RequireAuth"

type UserStats = {
likeCount: number
memberSince: string
siteCount: number
}

const Dashboard = async () => {
const { socialLogin } = useAuth()
const { token, userId } = useJwtStore()
const [stats, setStats] = useState<UserStats | null>(null)
useEffect(() => {
const fetchUserData = async () => {
if (!token || !userId) return
const res = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/users/${userId}`,
{ headers: { Authorization: `Bearer ${token}` } }
)
const { user } = await res.json()
setStats({
likeCount: user.likedUrls.length,
memberSince: user.createdAt,
siteCount: user.submittedUrls.length,
})
}
fetchUserData()
}, [token, userId])

return (
<RequireAuth>
<div className="flex h-full max-w-full flex-col items-center justify-center">
<div className="max-w-full break-words px-4">
<div className="flex items-center gap-4">
<div className="text-2xl/none font-bold text-shark-300">
Login with
</div>
{socialLogin && (
<div className="rounded-2xl bg-shark-600 px-2 py-1 text-sm/none">
{socialLogin.provider}
</div>
)}
</div>
<div className="mt-6 text-2xl/none text-shark-100">
{socialLogin ? `Email: ${socialLogin.email}` : "Web3 Login"}
</div>
<div className="mt-4 text-shark-200">
Member since {moment(stats?.memberSince).format("MMMM Do, YYYY")}
</div>
<div className="mt-12 text-2xl/none font-bold text-shark-300">
Websites submitted
</div>
<div className="mt-6 text-[56px]/none font-extrabold text-shark-50">
{stats?.siteCount ?? 0}
</div>
<div className="mt-10 text-2xl/none font-bold text-shark-300">
Likes submitted
</div>
<div className="mt-6 text-[56px]/none font-extrabold text-shark-50">
{stats?.likeCount ?? 0}
</div>
</div>
</div>
</RequireAuth>
)
}

export default Dashboard
53 changes: 53 additions & 0 deletions app/(stateless-toolbar)/landing/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Image from "next/image"

import CountdownTimer from "@/components/animated-counter"

import EthereumIcon from "/assets/ethereum-stroke.svg"

export default function Landing() {
return (
<main className="h-full bg-[hsl(124,61%,36%)] lg:h-full">
<div className="container flex h-full max-w-7xl flex-col items-center justify-center space-y-8 px-3 py-8 lg:flex-row lg:justify-between lg:space-x-6 lg:space-y-16 lg:px-16 xl:px-24">
<article className="flex flex-col items-center justify-center text-center">
<p className="font-dm font-medium tracking-wide xl:text-lg">
THESE WEBSITES HAVE BEEN ADDED BY
</p>
<h3 className="text-2xl font-bold xl:text-6xl">USERS LIKE YOU</h3>
<div id="spacer" className="p-4 xl:p-8"></div>
<p className="max-w-md font-dm text-sm font-medium tracking-wide lg:text-base">
THIS PROJECT USES STATE CHANNELS & RANDOM CONTENT FOR YOUR
ENTERTAINMENT
</p>
<div id="spacer" className="p-2"></div>
<section>
<div className="grid max-w-[360px] grid-cols-6 grid-rows-[1fr_2rem] border-2 border-primary">
<div className="relative col-span-1 col-start-1 row-span-1 flex items-center justify-center border-r-2 border-primary text-primary">
<Image
src={EthereumIcon}
width={21}
height={32}
alt={"Ethereum logo"}
/>
</div>
<div className="col-span-5 col-start-2 row-span-1 row-start-1 px-2 py-4">
<h3 className="text-base font-bold">ETHEREUM TECHNOLOGY</h3>
</div>
<div className="col-span-6 col-start-1 row-span-1 flex items-center justify-center border-t-2 border-primary">
<p className="text-xs uppercase tracking-wide">
GOOD VIBES ONLY (maybe)
</p>
</div>
</div>
</section>
</article>

<article className="flex flex-col items-center justify-center gap-y-2 text-center">
<h6 className="font-dm text-sm font-medium uppercase tracking-widest lg:text-lg">
Transmission starts in...
</h6>
<CountdownTimer from={10} />
</article>
</div>
</main>
)
}
Loading

0 comments on commit b510154

Please sign in to comment.