mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-04-26 01:09:02 -05:00
149 lines
4.2 KiB
TypeScript
149 lines
4.2 KiB
TypeScript
import {
|
|
Box,
|
|
Flex,
|
|
Input,
|
|
InputGroup,
|
|
InputLeftElement,
|
|
} from "@chakra-ui/react";
|
|
import { t, Trans } from "@lingui/macro";
|
|
import Breadcrumbs from "components/common/Breadcrumbs";
|
|
import MyLink from "components/common/MyLink";
|
|
import UserAvatar from "components/common/UserAvatar";
|
|
import { getEmojiFlag } from "countries-list";
|
|
import { useDebounce, useMyTheme } from "hooks/common";
|
|
import { setSearchParams } from "lib/setSearchParams";
|
|
import { Unpacked } from "lib/types";
|
|
import { GetStaticProps } from "next";
|
|
import Head from "next/head";
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/router";
|
|
import { getAllUsers, GetAllUsersData } from "prisma/queries/getAllUsers";
|
|
import { useEffect, useMemo, useState } from "react";
|
|
import { FaTwitter } from "react-icons/fa";
|
|
import { FiSearch } from "react-icons/fi";
|
|
|
|
interface Props {
|
|
users: GetAllUsersData;
|
|
}
|
|
|
|
const UserSearchPage = ({ users }: Props) => {
|
|
const router = useRouter();
|
|
const { gray } = useMyTheme();
|
|
|
|
const [filter, setFilter] = useState(getInitialFilterValue());
|
|
const debouncedFilter = useDebounce(filter);
|
|
|
|
useEffect(() => {
|
|
if (debouncedFilter.length < 3) {
|
|
setSearchParams("filter", undefined);
|
|
} else {
|
|
setSearchParams("filter", encodeURIComponent(debouncedFilter));
|
|
}
|
|
}, [debouncedFilter]);
|
|
|
|
const filteredUsers = useMemo(() => {
|
|
if (debouncedFilter.length < 3) return [];
|
|
|
|
return users.filter((u) => {
|
|
const normalizedFilter = debouncedFilter.toLowerCase();
|
|
const normalizedName = `${u.username}#${u.discriminator}`.toLowerCase();
|
|
|
|
if (normalizedName.includes(normalizedFilter)) return true;
|
|
|
|
const normalizedTwitter = u.profile?.twitterName
|
|
? u.profile.twitterName.toLowerCase()
|
|
: "";
|
|
|
|
if (normalizedTwitter.includes(normalizedFilter)) return true;
|
|
|
|
return false;
|
|
});
|
|
}, [debouncedFilter]);
|
|
|
|
return (
|
|
<>
|
|
<Head>
|
|
<meta name="robots" content="noindex" />
|
|
</Head>
|
|
<Breadcrumbs pages={[{ name: t`Users` }]} />
|
|
<Box color={gray} fontSize="sm" mb={4}>
|
|
<Trans>Search for users by their Discord tag or Twitter name</Trans>
|
|
</Box>
|
|
<InputGroup size="lg" maxW={80} mt={4} mb={6}>
|
|
<InputLeftElement
|
|
pointerEvents="none"
|
|
children={<Box as={FiSearch} color={gray} />}
|
|
/>
|
|
<Input
|
|
placeholder="Sendou#4059"
|
|
value={filter}
|
|
onChange={(e) => setFilter(e.target.value)}
|
|
/>
|
|
</InputGroup>
|
|
<Box mt={4}>
|
|
{filteredUsers.map((user) => (
|
|
<UserInfo key={user.discordId} user={user} />
|
|
))}
|
|
</Box>
|
|
{debouncedFilter.length >= 3 && !filteredUsers.length && (
|
|
<Box>No matching users found</Box>
|
|
)}
|
|
</>
|
|
);
|
|
|
|
function getInitialFilterValue() {
|
|
if (!router.query.filter || typeof router.query.filter !== "string")
|
|
return "";
|
|
|
|
return router.query.filter;
|
|
}
|
|
};
|
|
|
|
function UserInfo({ user }: { user: Unpacked<GetAllUsersData> }) {
|
|
return (
|
|
<Flex my={6} align="center">
|
|
<Link href={`/u/${user.discordId}`}>
|
|
<a>
|
|
<UserAvatar isSmall user={user} />
|
|
</a>
|
|
</Link>
|
|
<Box ml={4}>
|
|
<Box fontWeight="bold">
|
|
<MyLink
|
|
href={`/u/${user.discordId}`}
|
|
isColored={false}
|
|
prefetch={true}
|
|
>
|
|
{user.username}#{user.discriminator}
|
|
</MyLink>
|
|
{user.profile?.country ? (
|
|
<Box as="span" ml={2}>
|
|
{getEmojiFlag(user.profile.country)}
|
|
</Box>
|
|
) : null}
|
|
</Box>
|
|
{user.profile?.twitterName && (
|
|
<Flex align="center" fontSize="sm" mt={1}>
|
|
<Box as={FaTwitter} color="#00acee" mr={1} />
|
|
<MyLink
|
|
isExternal
|
|
href={`https://twitter.com/${user.profile.twitterName}`}
|
|
isColored={false}
|
|
>
|
|
{user.profile.twitterName}
|
|
</MyLink>
|
|
</Flex>
|
|
)}
|
|
</Box>
|
|
</Flex>
|
|
);
|
|
}
|
|
|
|
export const getStaticProps: GetStaticProps<Props> = async () => {
|
|
await getAllUsers();
|
|
|
|
return { props: { users: await getAllUsers() }, revalidate: 3600 };
|
|
};
|
|
|
|
export default UserSearchPage;
|