Skip to content

Commit 4b3e9dd

Browse files
committed
feat: search button
1 parent bc1ad47 commit 4b3e9dd

File tree

4 files changed

+125
-24
lines changed

4 files changed

+125
-24
lines changed
Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1+
import { Artwork, Character } from "@/types/characters";
2+
import { Comments } from "@/types/users";
13
import { USER_DEFAULT_AVATAR } from "@/utils/constants";
4+
import { Button } from "@mav/ui/components/buttons";
25
import Image from "next/image";
36
import { LuCheck } from "react-icons/lu";
47

58

6-
export default function Notification({ content, createdAt, read, senderAvatar, url, userAvatar }: {
7-
content: string
8-
read: boolean
9-
userAvatar: string | null
10-
senderAvatar: string | null
11-
url: string | null
12-
createdAt: Date
9+
export default function Notification({ content, createdAt, read, senderAvatar, senderHandle, url, userAvatar, artwork, character, comment }: {
10+
content: string
11+
read: boolean
12+
userAvatar: string | null
13+
senderHandle?: string
14+
senderAvatar: string | null
15+
url: string | null
16+
comment?: Comments | null
17+
artwork?: Artwork | null
18+
character?: Character | null
19+
createdAt: Date
1320
}) {
1421
const date = new Date(createdAt || "")
1522
const now = new Date()
@@ -20,11 +27,11 @@ export default function Notification({ content, createdAt, read, senderAvatar, u
2027
diff > 0 ? `${diff} day${diff > 1 ? "s" : ""} ago` : "Earlier Today"
2128

2229
// TODO: Read implementation
23-
30+
2431

2532
return (
2633
<div className="flex flex-row justify-between items-center gap-x-5 w-full">
27-
<div className="flex flex-row items-center gap-x-6 py-3">
34+
<div className="flex flex-row items-center gap-x-6 py-3 w-full">
2835
<div className="relative w-[50px] h-[50px]">
2936
<Image
3037
src={userAvatar ?? USER_DEFAULT_AVATAR}
@@ -41,12 +48,20 @@ export default function Notification({ content, createdAt, read, senderAvatar, u
4148
className="absolute -bottom-1 -right-2 rounded-full border-2 border-white shadow-md"
4249
/>
4350
</div>
44-
<div className="flex flex-col">
45-
<span>{content}</span>
51+
<div className="flex flex-col w-full gap-y-3">
52+
<span>{content.replace("%user%", senderHandle || "Someone")}</span>
53+
{comment && (
54+
<div className="bg-100 border-400 border rounded-md w-full px-3 py-2">{comment.content}</div>
55+
)}
4656
<span>{diffString}</span>
4757
</div>
4858
</div>
49-
<LuCheck size={20} className="text-green-500" />
59+
<Button
60+
icon={
61+
<LuCheck size={20} />
62+
}
63+
variant="tritery"
64+
/>
5065
</div>
5166
)
5267
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
"use client";
2+
3+
import { useState, useEffect, useRef, Fragment } from "react";
4+
import { Dialog, Menu, MenuButton, MenuItems, Transition } from "@headlessui/react";
5+
import { useRouter } from "next/navigation";
6+
import { LuSearch, LuX } from "react-icons/lu";
7+
import { Button } from "@mav/ui/components/buttons";
8+
import { InputField } from "@mav/ui/components/fields";
9+
10+
export default function SearchBar() {
11+
const [isOpen, setIsOpen] = useState(false);
12+
const [query, setQuery] = useState("");
13+
const router = useRouter();
14+
const inputRef = useRef<HTMLInputElement>(null);
15+
16+
useEffect(() => {
17+
const handleKeyDown = (event: KeyboardEvent) => {
18+
if (event.key === "/" && !isOpen) {
19+
event.preventDefault();
20+
setIsOpen(true);
21+
} else if (event.key === "Escape") {
22+
setIsOpen(false);
23+
}
24+
};
25+
document.addEventListener("keydown", handleKeyDown);
26+
return () => document.removeEventListener("keydown", handleKeyDown);
27+
}, [isOpen]);
28+
29+
useEffect(() => {
30+
if (isOpen) {
31+
setTimeout(() => inputRef.current?.focus(), 100);
32+
}
33+
}, [isOpen]);
34+
35+
const handleSearch = (e: React.FormEvent) => {
36+
e.preventDefault();
37+
setIsOpen(false);
38+
// TODO: Search logic
39+
};
40+
41+
return (
42+
<div className="top-full relative">
43+
{!isOpen && (
44+
<Button
45+
onClick={() => setIsOpen(true)}
46+
prefix={<LuSearch size={18} />}
47+
className="hover:!bg-100 w-64"
48+
variant="secondary"
49+
>
50+
Type
51+
<kbd className="bg-400 text-xs px-1 rounded">/</kbd>
52+
to search
53+
</Button>
54+
)}
55+
56+
<Transition
57+
show={isOpen}
58+
enter="transition duration-[200ms] ease"
59+
enterFrom="transform -translate-y-1 opacity-0"
60+
enterTo="transform opacity-100 translate-y-0"
61+
leave="transition duration-[200ms] ease"
62+
leaveTo="transform -translate-y-1 opacity-0"
63+
leaveFrom="transform translate-y-0 opacity-100"
64+
// @ts-expect-error
65+
className="translate-x-0 top-0"
66+
>
67+
<Dialog
68+
open={isOpen}
69+
onClose={() => setIsOpen(false)}
70+
className="fixed z-50 inset-0 overflow-y-auto top-3.5"
71+
>
72+
<div className="flex items-center justify-center w-full">
73+
<form onSubmit={handleSearch} className="flex items-center gap-x-2 w-2/3">
74+
<InputField
75+
ref={inputRef}
76+
type="text"
77+
value={query}
78+
onChange={(e) => setQuery(e.target.value)}
79+
placeholder="Search Character, Artist, Artwork, User..."
80+
81+
/>
82+
</form>
83+
</div>
84+
</Dialog>
85+
</Transition>
86+
</div>
87+
)
88+
}

apps/web/src/components/layouts/AppLayout/ActionsLoggedIn.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
import { Button } from "@mav/ui/components/buttons"
1010
import { LuBell, LuCheck, LuChevronDown, LuMinusCircle, LuPlus } from "react-icons/lu"
1111
import { Dropdown, DropdownItem } from "./Dropdown"
12-
import Image from "next/image"
1312
import Notification from "@/components/Notification"
1413

1514
const ICON = (
@@ -72,27 +71,31 @@ export function ActionsLoggedIn({
7271
variant="tritery"
7372
/>}
7473
items={
75-
<div className="flex flex-col items-center px-4 w-80">
74+
<div className="flex flex-col items-center px-4 w-[500px]">
7675
<div className="flex flex-row items-center justify-between w-full">
7776
<span className="text-xl">Notifications</span>
7877
<div className="flex flex-row">
79-
<Button variant="tritery" size={"big"} icon={<LuMinusCircle />} />
80-
<Button variant="tritery" size={"big"} icon={<LuCheck />} />
78+
<Button variant="tritery" icon={<LuMinusCircle size={20} />} />
79+
<Button variant="tritery" icon={<LuCheck size={20} />} />
8180
</div>
8281
</div>
8382
{user.notifications.length === 0 ? (
84-
<span className="text-gray-500 text-sm">No new notifications</span>
83+
<span className="text-500 text-sm">No new notifications</span>
8584
) : (
8685
user.notifications.slice(0, 5).map((notification) => (
8786
<Notification
8887
key={notification.id}
8988
content={notification.content}
89+
senderHandle={notification.sender ? notification.sender.handle : undefined}
9090
createdAt={notification.createdAt}
9191
read={notification.read}
9292
userAvatar={user.avatarUrl || "/UserProfile.png"}
9393
senderAvatar={
9494
notification.sender ? notification.sender.avatarUrl : null
9595
}
96+
comment={notification.comment}
97+
artwork={notification.artwork}
98+
character={notification.character}
9699
url={
97100
notification.artwork
98101
? `/artworks/${notification.artwork.id}`

apps/web/src/components/layouts/AppLayout/Navbar.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { MyArtverseIcon } from "@mav/ui/icons"
1010
import { LuMenu, LuSearch } from "react-icons/lu"
1111
import { ActionsLoggedIn } from "./ActionsLoggedIn"
1212
import { ActionsLoggedOut } from "./ActionsLoggedOut"
13+
import SearchBar from "@/components/SearchBar"
1314

1415
export function Navbar() {
1516
const { user, isLoading } = useAuth()
@@ -35,13 +36,7 @@ export function Navbar() {
3536
</Link>
3637
</div>
3738
<div className="flex items-center gap-x-4">
38-
<Button
39-
prefix={<LuSearch size={18} />}
40-
className="hover:!bg-100 w-64"
41-
variant="secondary"
42-
>
43-
Search
44-
</Button>
39+
<SearchBar />
4540
{!isLoading &&
4641
(user ? (
4742
<ActionsLoggedIn user={user} isRegistered={true} />

0 commit comments

Comments
 (0)