Skip to content

Commit

Permalink
feat(home): use new style home page
Browse files Browse the repository at this point in the history
  • Loading branch information
kangfenmao committed Jan 24, 2024
1 parent c0a6480 commit b3f80ca
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 80 deletions.
75 changes: 33 additions & 42 deletions frontend/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'
import { Link, useNavigate, useSearchParams } from 'react-router-dom'
import React, { useEffect, useState } from 'react'
import useTheme from '@/hooks/useTheme.ts'
import { hasPasscode, hasPermission, onSearch as search } from '@/utils'
Expand All @@ -7,12 +7,10 @@ import { getAxiosInstance } from '@/config/http.ts'
interface Props {}

const Navbar: React.FC<Props> = () => {
const location = useLocation()
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const keywords = searchParams.get('keywords') || ''
const [input, setInput] = useState(keywords)
const isHome = location.pathname === '/'
const [theme, setTheme] = useTheme()
const [showMenu, setShowMenu] = useState(true)

Expand All @@ -34,53 +32,46 @@ const Navbar: React.FC<Props> = () => {
setTimeout(() => setShowMenu(true), 500)
}

const navbarBg = isHome ? '' : 'bg-white dark:bg-black dark:bg-transparent-20'
const navbarBorder = isHome
? 'border-b border-transparent'
: 'border-b border-gray-200 dark:border-white dark:border-opacity-10'
const navbarBg = 'bg-white dark:bg-black dark:bg-transparent-20'
const navbarBorder = 'border-b border-gray-200 dark:border-white dark:border-opacity-10'

return (
<div
className={`flex flex-row h-16 items-center fixed top-0 left-0 right-0 ${navbarBorder} ${navbarBg}`}
style={{
zIndex: 100,
backgroundColor: isHome ? 'transparent' : 'var(--theme-navbar-color)'
backgroundColor: 'var(--theme-navbar-color)'
}}>
<div className="flex flex-row items-center justify-between m-auto w-full px-5 ">
{isHome && <div className="flex-1"></div>}
{!isHome && (
<Link to="/" className="flex flex-row items-center">
<img src="/public/icon-200x200.png" className="w-10 mr-2 hover:animate-spin" alt="" />
<span
style={{ fontFamily: 'Major Mono Display' }}
className="text-xl text-black dark:text-white">
VoRteX
</span>
</Link>
)}
{!isHome && (
<div className="flex-1 hidden sm:flex mx-8">
<section className="relative w-full rounded-full border border-black border-opacity-10 dark:border-white dark:border-opacity-20">
<input
type="text"
name="keywords"
value={input}
onChange={e => setInput(e.target.value)}
placeholder="Search"
className="w-full px-4 py-2 outline-none rounded-md bg-transparent"
onKeyDown={e => e.key === 'Enter' && onSearch()}
autoComplete="off"
required
/>
<button
type="button"
onClick={onSearch}
className="absolute top-0 bottom-0 right-0 w-12 flex flex-row justify-center items-center cursor-pointer opacity-70">
<i className="iconfont icon-search opacity-70 text-black dark:text-white text-1xl mr-1"></i>
</button>
</section>
</div>
)}
<Link to="/" className="flex flex-row items-center">
<img src="/public/icon-200x200.png" className="w-10 mr-2 hover:animate-spin" alt="" />
<span
style={{ fontFamily: 'Major Mono Display' }}
className="text-xl text-black dark:text-white">
VoRteX
</span>
</Link>
<div className="flex-1 hidden sm:flex mx-8">
<section className="relative w-full rounded-full border border-black border-opacity-10 dark:border-white dark:border-opacity-20">
<input
type="text"
name="keywords"
value={input}
onChange={e => setInput(e.target.value)}
placeholder="Search"
className="w-full px-4 py-2 outline-none rounded-md bg-transparent"
onKeyDown={e => e.key === 'Enter' && onSearch()}
autoComplete="off"
required
/>
<button
type="button"
onClick={onSearch}
className="absolute top-0 bottom-0 right-0 w-12 flex flex-row justify-center items-center cursor-pointer opacity-70">
<i className="iconfont icon-search opacity-70 text-black dark:text-white text-1xl mr-1"></i>
</button>
</section>
</div>
<div className="flex flex-row items-center">
<label className="swap swap-rotate opacity-60 hover:opacity-80 transition-opacity">
{/* this hidden checkbox controls the state */}
Expand Down
41 changes: 41 additions & 0 deletions frontend/src/screens/HomeScreen/GroupedNotes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react'
import { groupBy } from 'lodash-es'
import { NoteType } from '@/types'
import { displayName } from '@/utils'
import { Link } from 'react-router-dom'
import dayjs from 'dayjs'

interface Props {
data: NoteType[]
}

const GroupedNotes: React.FC<Props> = ({ data }) => {
const groupedData = groupBy(data, item => {
return dayjs(item.created_at).format('MM/DD')
})

return (
<div>
{Object.entries(groupedData).map(([letter, items]) => (
<div key={letter} className="mb-6">
<h2 className="text-3xl font-bold opacity-30 mt-2">{letter}</h2>
<hr className="my-2 border-b-1 border-black border-opacity-10 dark:border-white dark:border-opacity-10" />
<ul>
{items.map(note => (
<div className="py-1 flex flex-row justify-between" key={note.id}>
<Link
to={`/notes/${note.id}`}
className="text-black hover:text-black dark:text-white dark:hover:text-white opacity-70 hover:opacity-90 line-clamp-1">
{displayName(note.name)}
</Link>
<span className="text-gray-500">{dayjs(note.created_at).format('YYYY/MM/DD')}</span>
</div>
))}
</ul>
</div>
))}
</div>
)
}

export default GroupedNotes
74 changes: 36 additions & 38 deletions frontend/src/screens/HomeScreen/index.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,44 @@
import React, { useState } from 'react'
import RecentlyNotes from '@/components/RecentlyNotes.tsx'
import { useNavigate } from 'react-router-dom'
import { onSearch as search } from '@/utils'
import React, { useEffect, useState } from 'react'
import { NoteType } from '@/types'
import useRequest from '@/hooks/useRequest.ts'
import useDebouncedValue from '@/hooks/useDebouncedValue.ts'
import LoadingView from '@/components/LoadingView.tsx'
import { isEmpty } from 'lodash-es'
import GroupedNotes from './GroupedNotes.tsx'
import EmptyView from '@/components/EmptyView.tsx'

let cachedNotes: NoteType[] = []

const HomeScreen: React.FC = () => {
const [keywords, setKeywords] = useState('')
const navigate = useNavigate()
const [notes, setNotes] = useState<NoteType[]>(cachedNotes)
const page = 1
const limit = 12
const { data, isLoading } = useRequest<NoteType[]>({
method: 'GET',
url: `notes?page=${page}&limit=${limit}&sort=updated_at:desc`
})

const loading = useDebouncedValue(false, isLoading, 1000)

useEffect(() => {
data && setNotes(data)
}, [data])

const onSearch = search.bind(this, keywords, navigate)
useEffect(() => {
return () => {
if (notes.length) {
cachedNotes = notes
}
}
}, [notes])

return (
<main className="flex flex-1">
<div className="flex flex-col mt-28 sm:m-auto items-center w-full px-5 transition-all duration-150 max-w-xl">
<div className="flex flex-col items-center">
<img src="/public/icon-200x200.png" className="w-28 cursor-pointer" alt="" />
<span
style={{ fontFamily: 'Major Mono Display' }}
className="text-sm mb-5 mt-1 select-none">
Vortexnotes
</span>
</div>
<section className="relative mb-10 w-full border border-black border-opacity-20 dark:border-white dark:border-opacity-30 rounded-md">
<input
type="text"
name="keywords"
value={keywords}
onChange={e => setKeywords(e.target.value)}
placeholder="Search Notes"
className="px-4 py-3 w-full outline-none bg-white dark:bg-zinc-800 rounded-md"
onKeyDown={e => e.key === 'Enter' && onSearch()}
autoComplete="off"
autoFocus
required
/>
<button
type="button"
onClick={onSearch}
className="absolute top-0 bottom-0 right-0 w-12 flex flex-row justify-center items-center cursor-pointer">
<i className="iconfont icon-search text-2xl opacity-50 hover:opacity-90 transition-opacity"></i>
</button>
</section>
<RecentlyNotes />
<main className="w-full">
<div className="container mx-auto px-5 mt-20 max-w-lg sm:max-w-6xl">
{loading && isEmpty(notes) && <LoadingView />}
{!loading && isEmpty(notes) && <EmptyView title="No notes" />}
{!loading && !isEmpty(notes) && <GroupedNotes data={notes} />}
<footer className="h-10"></footer>
</div>
</main>
)
Expand Down

0 comments on commit b3f80ca

Please sign in to comment.