File tree Expand file tree Collapse file tree 11 files changed +165
-16
lines changed
Expand file tree Collapse file tree 11 files changed +165
-16
lines changed Original file line number Diff line number Diff line change @@ -10,6 +10,9 @@ import type { Hook as UseHook } from "./share/types.ts";
1010
1111const UserListSchema = z . array ( UserSchema ) ;
1212
13+ export function useAll ( ) : Hook < User [ ] > {
14+ return useCustomizedSWR ( "users::all" , all , UserListSchema ) ;
15+ }
1316export function useRecommended ( ) : UseHook < User [ ] > {
1417 const url = endpoints . recommendedUsers ;
1518 return useAuthorizedData < User [ ] > ( url ) ;
@@ -28,6 +31,11 @@ export function usePendingFromMe(): Hook<User[]> {
2831 ) ;
2932}
3033
34+ async function all ( ) : Promise < User [ ] > {
35+ const res = await credFetch ( "GET" , endpoints . users ) ;
36+ return res . json ( ) ;
37+ }
38+
3139async function matched ( ) : Promise < User [ ] > {
3240 const res = await credFetch ( "GET" , endpoints . matchedUsers ) ;
3341 return res . json ( ) ;
@@ -131,6 +139,8 @@ export async function deleteAccount(): Promise<void> {
131139 const res = await credFetch ( "DELETE" , endpoints . me ) ;
132140 if ( res . status !== 204 )
133141 throw new Error (
134- `failed to delete account: expected status code 204, but got ${ res . status } with text ${ await res . text ( ) } ` ,
142+ `failed to delete account: expected status code 204, but got ${
143+ res . status
144+ } with text ${ await res . text ( ) } `,
135145 ) ;
136146}
Original file line number Diff line number Diff line change @@ -13,7 +13,7 @@ export default function ChatPageLayout({
1313 < div className = "absolute top-14 right-0 bottom-14 left-0 overflow-y-auto sm:top-16" >
1414 { children }
1515 </ div >
16- < BottomBar activeTab = "2_chat " />
16+ < BottomBar activeTab = "3_chat " />
1717 </ NavigateByAuthState >
1818 ) ;
1919}
Original file line number Diff line number Diff line change 11import BottomBar from "~/components/BottomBar" ;
22import Header from "~/components/Header" ;
3+ import { NavigateByAuthState } from "~/components/common/NavigateByAuthState" ;
34
45export default function FriendsPageLayout ( {
56 children,
67} : {
78 children : React . ReactNode ;
89} ) {
910 return (
10- < >
11+ < NavigateByAuthState type = "toLoginForUnauthenticated" >
1112 < Header title = "フレンド/Friends" />
1213 < div className = "absolute top-14 right-0 bottom-14 left-0 overflow-y-auto sm:top-16" >
1314 { children }
1415 </ div >
1516 < BottomBar activeTab = "1_friends" />
16- </ >
17+ </ NavigateByAuthState >
1718 ) ;
1819}
Original file line number Diff line number Diff line change 11import BottomBar from "~/components/BottomBar" ;
22import Header from "~/components/Header" ;
3+ import { NavigateByAuthState } from "~/components/common/NavigateByAuthState" ;
34
45export default function HomePageLayout ( {
56 children,
67} : {
78 children : React . ReactNode ;
89} ) {
910 return (
10- < >
11+ < NavigateByAuthState type = "toLoginForUnauthenticated" >
1112 < Header title = "ホーム/Home" />
1213 < div className = "relative top-14 right-0 bottom-14 left-0 overflow-y-auto sm:top-16" >
1314 { children }
1415 </ div >
1516 < BottomBar activeTab = "0_home" />
16- </ >
17+ </ NavigateByAuthState >
1718 ) ;
1819}
Original file line number Diff line number Diff line change 1+ import BottomBar from "~/components/BottomBar" ;
2+ import Header from "~/components/Header" ;
3+
4+ export default function HomePageLayout ( {
5+ children,
6+ } : {
7+ children : React . ReactNode ;
8+ } ) {
9+ return (
10+ < >
11+ < Header title = "検索/Search" />
12+ < div className = "absolute top-14 right-0 bottom-14 left-0 overflow-y-auto sm:top-16" >
13+ { children }
14+ </ div >
15+ < BottomBar activeTab = "2_search" />
16+ </ >
17+ ) ;
18+ }
Original file line number Diff line number Diff line change 1+ "use client" ;
2+
3+ import type React from "react" ;
4+ import { useState } from "react" ;
5+ import Search from "~/components/search/search" ;
6+ import Table from "~/components/search/table" ;
7+
8+ export default function SearchPage ( {
9+ searchParams,
10+ } : {
11+ searchParams ?: {
12+ query ?: string ;
13+ page ?: string ;
14+ } ;
15+ } ) {
16+ const [ query , setQuery ] = useState < string > ( searchParams ?. query ?? "" ) ;
17+
18+ return (
19+ < div className = "flex min-h-screen justify-center " >
20+ < div className = "w-full" >
21+ < h2 className = "m-5 mb-4 font-bold text-2xl" > ユーザー検索</ h2 >
22+ < Search placeholder = "検索" setSearchString = { setQuery } />
23+ < Table query = { query } />
24+ </ div >
25+ </ div >
26+ ) ;
27+ }
Original file line number Diff line number Diff line change @@ -12,7 +12,7 @@ export default function SettingsPageLayout({
1212 < div className = "absolute top-14 right-0 bottom-14 left-0 overflow-y-auto sm:top-16" >
1313 { children }
1414 </ div >
15- < BottomBar activeTab = "3_settings " />
15+ < BottomBar activeTab = "4_settings " />
1616 </ >
1717 ) ;
1818}
Original file line number Diff line number Diff line change @@ -3,9 +3,10 @@ import { MdHome } from "react-icons/md";
33import { MdPeople } from "react-icons/md" ;
44import { MdChat } from "react-icons/md" ;
55import { MdSettings } from "react-icons/md" ;
6+ import { MdSearch } from "react-icons/md" ;
67
78type Props = {
8- activeTab : "0_home" | "1_friends" | "2_chat " | "3_settings " ;
9+ activeTab : "0_home" | "1_friends" | "2_search " | "3_chat" | "4_settings ";
910} ;
1011
1112function BottomBarCell ( {
@@ -22,7 +23,9 @@ function BottomBarCell({
2223 return (
2324 < Link
2425 href = { href }
25- className = { `focus:bg-gray-300 ${ isActive ? "active text-primary" : "text-secondary" } ` }
26+ className = { `focus:bg-gray-300 ${
27+ isActive ? "active text-primary" : "text-secondary"
28+ } `}
2629 >
2730 { iconComponent }
2831 < span
@@ -50,16 +53,22 @@ export default function BottomBar(props: Props) {
5053 isActive = { activeTab === "1_friends" }
5154 iconComponent = { < MdPeople className = "text-2xl" /> }
5255 />
56+ < BottomBarCell
57+ label = "Search"
58+ href = "/search"
59+ isActive = { activeTab === "2_search" }
60+ iconComponent = { < MdSearch className = "text-2xl" /> }
61+ />
5362 < BottomBarCell
5463 label = "Chat"
5564 href = "/chat"
56- isActive = { activeTab === "2_chat " }
65+ isActive = { activeTab === "3_chat " }
5766 iconComponent = { < MdChat className = "text-2xl" /> }
5867 />
5968 < BottomBarCell
6069 label = "Settings"
6170 href = "/settings"
62- isActive = { activeTab === "3_settings " }
71+ isActive = { activeTab === "4_settings " }
6372 iconComponent = { < MdSettings className = "text-2xl" /> }
6473 />
6574 </ div >
Original file line number Diff line number Diff line change 1+ "use client" ;
2+
3+ import { usePathname , useSearchParams } from "next/navigation" ;
4+ import { MdOutlineSearch } from "react-icons/md" ;
5+
6+ type Props = { placeholder : string ; setSearchString : ( s : string ) => void } ;
7+ export default function Search ( { placeholder, setSearchString } : Props ) {
8+ const searchParams = useSearchParams ( ) ;
9+ const pathname = usePathname ( ) ;
10+
11+ function handleSearch ( term : string ) {
12+ setSearchString ( term ) ;
13+ const params = new URLSearchParams ( searchParams ) ;
14+ if ( term ) {
15+ params . set ( "query" , term ) ;
16+ } else {
17+ params . delete ( "query" ) ;
18+ }
19+ const newUrl = `${ pathname } ?${ params . toString ( ) } ` ;
20+ history . replaceState ( undefined , "" , newUrl ) ;
21+ }
22+
23+ return (
24+ < div className = "relative mr-5 ml-5 flex flex-1 flex-shrink-0" >
25+ < label htmlFor = "search" className = "sr-only" >
26+ Search
27+ </ label >
28+ < input
29+ className = " block w-full rounded-md border border-gray-200 py-[9px] pl-10 text-sm outline-none placeholder:text-gray-500 focus:border-primary focus:ring-1 focus:ring-primary"
30+ placeholder = { placeholder }
31+ onChange = { ( e ) => {
32+ handleSearch ( e . target . value ) ;
33+ } }
34+ defaultValue = { searchParams . get ( "query" ) ?. toString ( ) }
35+ />
36+ < MdOutlineSearch className = "-translate-y-1/2 absolute top-1/2 left-3 h-[18px] w-[18px] text-gray-500 peer-focus:text-gray-900" />
37+ </ div >
38+ ) ;
39+ }
Original file line number Diff line number Diff line change 1+ "use client" ;
2+ import { useMemo } from "react" ;
3+ import { useAll , useMyID } from "~/api/user" ;
4+ import { useModal } from "../common/modal/ModalProvider" ;
5+ import { HumanListItem } from "../human/humanListItem" ;
6+
7+ export default function UserTable ( { query } : { query : string } ) {
8+ const { openModal } = useModal ( ) ;
9+ const {
10+ state : { data } ,
11+ } = useAll ( ) ;
12+ const {
13+ state : { data : myId } ,
14+ } = useMyID ( ) ;
15+ const initialData = useMemo ( ( ) => {
16+ return data ?. filter ( ( item ) => item . id !== myId && item . id !== 0 ) ?? null ;
17+ } , [ data , myId ] ) ;
18+ const users = query
19+ ? initialData ?. filter ( ( user ) =>
20+ user . name . toLowerCase ( ) . includes ( query . toLowerCase ( ) ) ,
21+ )
22+ : initialData ;
23+
24+ return (
25+ < div >
26+ { users ?. map ( ( user ) => (
27+ < HumanListItem
28+ key = { user . id }
29+ id = { user . id }
30+ name = { user . name }
31+ pictureUrl = { user . pictureUrl }
32+ onOpen = { ( ) => openModal ( user ) }
33+ />
34+ ) ) }
35+ </ div >
36+ ) ;
37+ }
You can’t perform that action at this time.
0 commit comments