Skip to content

Commit

Permalink
Merge pull request #82 from /issues/76
Browse files Browse the repository at this point in the history
Issues/76
  • Loading branch information
nasubi-dev authored Jun 23, 2024
2 parents f8f7b77 + b11609e commit 01bdf6e
Show file tree
Hide file tree
Showing 14 changed files with 276 additions and 200 deletions.
2 changes: 0 additions & 2 deletions functions/api/[[catchall]].ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ export const onRequest: PagesFunction<Env> = async ({ request, env }) => {
const url = new URL(req.url);
const params = new URLSearchParams(url.search);

console.log(url);

const baseUrl = "https://api.esa.io/v1";
const newUrl = new URL(
baseUrl + url.pathname.replace(/^\/api/, "") + "?" + params.toString(),
Expand Down
2 changes: 1 addition & 1 deletion src/assets/members.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"posts_count": 0,
"joined_at": "2022-09-17T01:35:57+09:00",
"last_posted_at": "2022-09-17T01:35:57+09:00",
"email": "zzzzzz"
"email": "[email protected]"
},
{
"myself": false,
Expand Down
6 changes: 4 additions & 2 deletions src/components/Redirects.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { type ReactNode } from "react";
import { useLocation } from "react-router-dom";
import { $hasAuthenticated } from "@/lib/stores/auth";
import { redirect } from "@/router";
import { Navigate } from "@/router";

export function Redirects({ children }: { children: ReactNode }): ReactNode {
const { pathname } = useLocation();

const isInPublicPaths = pathname === "/" || pathname.startsWith("/auth");
if (!$hasAuthenticated.get() && !isInPublicPaths) {
redirect("/");
// eslint-disable-next-line no-console
console.warn("Member is not authenticated; Redirecting to `/`...");
return <Navigate replace to="/ranking" />;
}

return children;
Expand Down
5 changes: 4 additions & 1 deletion src/components/member/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ export function MemberCard({
return (
<TableRow
onClick={() => {
if (member.email == null) {
throw new Error("Member email is undefined");
}
navigate("/members/:id", {
params: {
id: member.email.toString(),
id: member.email,
},
});
}}
Expand Down
25 changes: 13 additions & 12 deletions src/components/member/RankingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@ import { Avatar, Box, Flex, Text } from "@radix-ui/themes";
import { type ReactElement } from "react";
import styled from "styled-components";
import { Link } from "@/router";
import { type Member } from "@/types/member";

export function RankingCard({
memberEmail,
memberName,
memberIcon,
index,
member,
point,
idx,
}: {
memberEmail: string;
memberName: string;
memberIcon: string;
index: number;
member: Member;
point: number;
idx: number;
}): ReactElement {
const { name, email, icon } = member;

if (email == null) throw new Error("email is null");

const BoxStyle = styled(Box)`
border-bottom: 1px solid;
border-color: #cbd5e1;
Expand All @@ -24,16 +25,16 @@ export function RankingCard({
`;

return (
<Link params={{ id: memberEmail }} to="/members/:id">
<Link params={{ id: email }} to="/members/:id">
<BoxStyle>
<Flex align="center" gap="6" ml="10rem" mr="10rem">
<Text mr="3rem" size="8" weight="bold">
{index + 1}
{idx + 1}
</Text>
<Avatar fallback="T" radius="full" size="8" src={memberIcon} />
<Avatar fallback="T" radius="full" size="8" src={icon} />
<Flex align="center" direction="column">
<Text as="div" size="7" weight="bold">
{memberName}
{name}
</Text>
<Text as="div" color="gray" size="7">
{point}pt
Expand Down
13 changes: 6 additions & 7 deletions src/components/ranking/LogRecentUnlocked.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import SampleMembers from "@/assets/members.json";
import { Link } from "@/router";
import { type Member } from "@/types/member";
import { type Achievement } from "@/types/post-data/achievements";
import { type UnlockedAchievement } from "@/types/post-data/unlocked-achievements";

const BoxStyle = styled(Box)`
border-bottom: 1px solid;
Expand All @@ -15,14 +16,12 @@ const BoxStyle = styled(Box)`
`;

export function LogRecentUnlocked({
achievementID,
unlockedDate,
memberEmail,
unlockedAchievement,
}: {
achievementID: number;
unlockedDate: string;
memberEmail: string;
unlockedAchievement: UnlockedAchievement;
}): ReactElement {
const { memberEmail, achievementID, createdAt } = unlockedAchievement;

const DateStyle = styled(Text)`
padding-left: 10rem;
`;
Expand All @@ -48,7 +47,7 @@ export function LogRecentUnlocked({
{achievement.name}
</Text>
<DateStyle color="gray" size="1">
{unlockedDate.slice(0, 10)}
{createdAt.toString().slice(0, 10)}
</DateStyle>
</Box>
</Flex>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/db/_esaDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function useEsaDB<T>(
const fetch = async (): Promise<T> => {
const postsId = await searchPostId();
const { body_md } = await fetchPostByPostId(postsId);
return await config.schema.validate(JSON.parse(body_md));
return await config.schema.validate(JSON.parse(body_md).data);
};

const create = async (): Promise<
Expand Down
47 changes: 38 additions & 9 deletions src/pages/achievements/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import { Box, Table } from "@radix-ui/themes";
import { type ReactElement } from "react";
import { useEffect, type ReactElement } from "react";
import styled from "styled-components";
import Achievements from "@/assets/achievements.json";
import useSWR from "swr";
import { match } from "ts-pattern";
import { AchievementCard } from "@/components/achievements/Card";
import { useAchievements } from "@/hooks/db/achievements";
import { useTeam } from "@/hooks/teams";
import { S } from "@/lib/consts";
import { type Achievement } from "@/types/post-data/achievements";

const BoxStyle = styled(Box)`
Expand All @@ -16,9 +20,32 @@ const ScrollStyle = styled.div`
`;

export default function Page(): ReactElement {
return (
<BoxStyle width="70%">
<ScrollStyle>
const { init, fetch } = useAchievements(useTeam);
const swrAchievements = useSWR("achievements", fetchAchievements);

async function fetchAchievements(): Promise<{
achievements: Achievement[];
}> {
const achievements = await fetch();

if (achievements == null)
throw new Error("No unlockedAchievements found.");

return {
achievements,
};
}



useEffect(() => {
void init();
}, []);

return match(swrAchievements)
.with(S.Loading, () => <div>Loading...</div>)
.with(S.Success, ({ data:{achievements} }) => (
<BoxStyle width="70%">
<Table.Root>
<Table.Header>
<Table.Row>
Expand All @@ -30,7 +57,7 @@ export default function Page(): ReactElement {
</Table.Header>

<Table.Body>
{Achievements.achievements.map((achievement) => {
{achievements.map((achievement) => {
const typedAchievement = achievement as unknown as Achievement;
return (
<AchievementCard
Expand All @@ -41,7 +68,9 @@ export default function Page(): ReactElement {
})}
</Table.Body>
</Table.Root>
</ScrollStyle>
</BoxStyle>
);
</BoxStyle>
))
.otherwise(({ error }) => {
throw error;
});
}
18 changes: 14 additions & 4 deletions src/pages/auth/callback/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useStore } from "@nanostores/react";
import { Card, Flex } from "@radix-ui/themes";
import { Button, Flex } from "@radix-ui/themes";
import { type ReactElement } from "react";
import styled from "styled-components";
import useSWR from "swr";
Expand All @@ -13,26 +13,36 @@ import { useNavigate } from "@/router";
import { type AccessTokenData } from "@/types/auth";

function TeamSelector(): ReactElement {
const navigate = useNavigate();
const { fetchJoinedTeams, markTeamNameAsSelected } = useMember();
const swrJoinedTeams = useSWR("joinedTeams", fetchJoinedTeams);

const FlexStyled = styled(Flex)`
gap: 1rem;
gap: 15rem;
`;

const ButtonStyle = styled(Button)`
transform: scale(2);
padding: 0;
height: 100px;
width: 100px;
`;

return match(swrJoinedTeams)
.with(S.Loading, () => <p>Loading...</p>)
.with(S.Success, ({ data }) => (
<FlexStyled>
{data.map((team) => (
<Card
<ButtonStyle
key={team.name}
onClick={() => {
markTeamNameAsSelected(team.name);
navigate("/ranking");
}}
size="4"
>
<img alt={team.name} src={team.icon} />
</Card>
</ButtonStyle>
))}
</FlexStyled>
))
Expand Down
102 changes: 69 additions & 33 deletions src/pages/members/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { Box, Table } from "@radix-ui/themes";
import { type ReactElement } from "react";
import { useEffect, type ReactElement } from "react";
import styled from "styled-components";
import SampleMember from "@/assets/members.json";
import SampleUnlockedAchievements from "@/assets/unlockedAchievements.json";
// import SampleMember from "@/assets/members.json";
// import SampleUnlockedAchievements from "@/assets/unlockedAchievements.json";
import useSWR from "swr";
import { match } from "ts-pattern";
import { MemberCard } from "@/components/member/Card";
import { useUnlockedAchievements } from "@/hooks/db/unlocked-achievements";
import { useTeam } from "@/hooks/teams";
import { S } from "@/lib/consts";
import { type Member } from "@/types/member";

type MembersWithUnlockedCount = Array<
Member & {
unlockedCount: number;
}
>;

const BoxStyle = styled(Box)`
margin: 0 auto;
`;
Expand All @@ -17,35 +28,60 @@ const ScrollStyle = styled.div`
`;

export default function Page(): ReactElement {
let point: number = 0;
return (
<BoxStyle width="70%">
<ScrollStyle>
<Table.Root>
<Table.Header>
<Table.Row>
<Table.ColumnHeaderCell> </Table.ColumnHeaderCell>
<Table.ColumnHeaderCell>名前</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell>ポイント</Table.ColumnHeaderCell>
</Table.Row>
</Table.Header>

<Table.Body>
{SampleMember.members.map((e: any) => {
const member: Member = e as Member;
point = 0;
SampleUnlockedAchievements.unlockedAchievements.forEach(
(unlockedAchievement) => {
if (unlockedAchievement.memberEmail === member.email) {
point += 1;
}
},
);
return <MemberCard key="index" member={member} point={point} />;
})}
</Table.Body>
</Table.Root>
</ScrollStyle>
</BoxStyle>
const { fetchMembers } = useTeam();
const { init, fetch } = useUnlockedAchievements(useTeam);
const swrMembersWithUnlockedCount = useSWR(
"membersWithUnlockedCount",
fetchMembersWithUnlockedCount,
);

async function fetchMembersWithUnlockedCount(): Promise<MembersWithUnlockedCount> {
const members = await fetchMembers();
const unlockedAchievements = await fetch();

if (unlockedAchievements == null)
throw new Error("No unlockedAchievements found.");

return members
.map((m) => {
const unlockedCount = unlockedAchievements.filter(
(u) => u.memberEmail === m.email,
).length;
return {
...m,
unlockedCount,
};
})
.sort((a, b) => b.unlockedCount - a.unlockedCount);
}

useEffect(() => {
void init();
}, []);

return match(swrMembersWithUnlockedCount)
.with(S.Loading, () => <div>Loading...</div>)
.with(S.Success, ({ data }) => (
<BoxStyle width="70%">
<Table.Root>
<Table.Header>
<Table.Row>
<Table.ColumnHeaderCell> </Table.ColumnHeaderCell>
<Table.ColumnHeaderCell>名前</Table.ColumnHeaderCell>
<Table.ColumnHeaderCell>ポイント</Table.ColumnHeaderCell>
</Table.Row>
</Table.Header>

<Table.Body>
{data.map((m, idx) => (
// eslint-disable-next-line react/no-array-index-key
<MemberCard key={idx} member={m} point={m.unlockedCount} />
))}
</Table.Body>
</Table.Root>
</BoxStyle>
))
.otherwise(({ error }) => {
throw error;
});
}
Loading

0 comments on commit 01bdf6e

Please sign in to comment.