Skip to content

Commit

Permalink
対戦履歴の画面(プロフィール画面の中に)を実装 (#164)
Browse files Browse the repository at this point in the history
* [frontend] Add match history page
* [backend] Remove UserGuard from history controller
- Order history by date
* [backend] Add match history seed data
  • Loading branch information
usatie authored Dec 22, 2023
1 parent 2bf2851 commit 2854926
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 6 deletions.
58 changes: 56 additions & 2 deletions backend/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const prisma = new PrismaClient();

const roundsOfHashing = 10;

async function main() {
async function seedUsers() {
const userNames = ['Susami', 'Thara', 'Kakiba', 'Shongou', 'Test'];
const userData = userNames.map((name) => ({
email: `${name.toLowerCase()}@example.com`,
Expand All @@ -17,7 +17,7 @@ async function main() {
),
avatarURL: `/avatar/${name.toLowerCase()}.jpg`,
}));
const users = await Promise.all(
return Promise.all(
userData.map(async (user) => {
return await prisma.user.upsert({
where: { email: user.email },
Expand All @@ -26,7 +26,9 @@ async function main() {
});
}),
);
}

async function seedRooms(users) {
const user1 = users[0];
const user2 = users[1];
const user3 = users[2];
Expand Down Expand Up @@ -62,6 +64,58 @@ async function main() {
}
}

async function seedMatchHistory() {
const dtos = [
{ winner: { userId: 1, score: 10 }, loser: { userId: 2, score: 4 } },
{ winner: { userId: 1, score: 10 }, loser: { userId: 3, score: 7 } },
{ winner: { userId: 1, score: 10 }, loser: { userId: 4, score: 3 } },
{ winner: { userId: 1, score: 10 }, loser: { userId: 5, score: 4 } },
{ winner: { userId: 2, score: 10 }, loser: { userId: 1, score: 5 } },
{ winner: { userId: 2, score: 10 }, loser: { userId: 3, score: 2 } },
{ winner: { userId: 2, score: 10 }, loser: { userId: 4, score: 1 } },
{ winner: { userId: 2, score: 10 }, loser: { userId: 5, score: 2 } },
{ winner: { userId: 3, score: 10 }, loser: { userId: 1, score: 0 } },
{ winner: { userId: 3, score: 10 }, loser: { userId: 2, score: 0 } },
{ winner: { userId: 3, score: 10 }, loser: { userId: 4, score: 2 } },
{ winner: { userId: 3, score: 10 }, loser: { userId: 5, score: 2 } },
{ winner: { userId: 4, score: 10 }, loser: { userId: 1, score: 5 } },
{ winner: { userId: 4, score: 10 }, loser: { userId: 2, score: 0 } },
{ winner: { userId: 4, score: 10 }, loser: { userId: 3, score: 2 } },
{ winner: { userId: 4, score: 10 }, loser: { userId: 5, score: 2 } },
{ winner: { userId: 5, score: 10 }, loser: { userId: 1, score: 5 } },
];

return Promise.all(
dtos.map((dto) =>
prisma.match.create({
data: {
players: {
create: [
{
userId: dto.winner.userId,
score: dto.winner.score,
winLose: 'WIN',
},
{
userId: dto.loser.userId,
score: dto.loser.score,
winLose: 'LOSE',
},
],
},
result: 'COMPLETE',
},
}),
),
);
}

async function main() {
const users = await seedUsers();
await seedRooms(users);
await seedMatchHistory();
}

main()
.catch((e) => {
console.error(e);
Expand Down
3 changes: 1 addition & 2 deletions backend/src/history/history.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
ApiTags,
} from '@nestjs/swagger';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
import { UserGuard } from 'src/user/user.guard';
import { CreateHistoryDto } from './dto/create-history.dto';
import { HistoryService } from './history.service';

Expand All @@ -32,7 +31,7 @@ export class HistoryController {
}

@Get('user/:userId/history')
@UseGuards(JwtAuthGuard, UserGuard)
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOkResponse()
findAll(@Param('userId', ParseIntPipe) userId: number) {
Expand Down
3 changes: 3 additions & 0 deletions backend/src/history/history.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ export class HistoryService {
},
},
},
orderBy: {
createdAt: 'desc',
},
...SelectHistory,
});
}
Expand Down
31 changes: 31 additions & 0 deletions frontend/app/lib/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,3 +522,34 @@ export async function unfriend(friendId: number) {
return "Success";
}
}

export type MatchDetailEntity = {
score: number;
winLose: "WIN" | "LOSE";
user: PublicUserEntity;
};

export type MatchHistoryEntity = {
id: number;
players: MatchDetailEntity[];
result: "COMPLETE" | "INCOMPLETE";
createdAt: string;
};

export async function getMatchHistory(
userId: number,
): Promise<MatchHistoryEntity[]> {
console.log(`${process.env.API_URL}/user/${userId}/history`);
const res = await fetch(`${process.env.API_URL}/user/${userId}/history`, {
headers: {
Authorization: "Bearer " + getAccessToken(),
},
});
if (!res.ok) {
console.error("getMatchHistory error: ", await res.json());
return [];
} else {
const matchHistory = await res.json();
return matchHistory;
}
}
56 changes: 56 additions & 0 deletions frontend/app/ui/user/match-history.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { MatchDetailEntity, getMatchHistory } from "@/app/lib/actions";
import Link from "next/link";
import { Avatar } from "./avatar";

function MatchDetailItem({
detail,
isProfileUser,
}: {
detail: MatchDetailEntity;
isProfileUser: boolean;
}) {
const textColor = isProfileUser
? detail.winLose === "WIN"
? "text-green-500"
: "text-red-500"
: "";
return (
<Link href={`/user/${detail.user.id}`}>
<div className="flex flex-col gap-2">
<div className="flex gap-2 items-center">
<Avatar avatarURL={detail.user.avatarURL} size="medium" />
<div>{detail.user.name}</div>
<div className={`font-bold ${textColor}`}>
{detail.winLose} ({detail.score})
</div>
</div>
</div>
</Link>
);
}

export default async function MatchHistory({ userId }: { userId: number }) {
const history = await getMatchHistory(userId);
return (
<div className="flex flex-col gap-2">
<div className="text-xl font-bold">Match History</div>
<div className="flex flex-col gap-2">
{history.map((match) => {
return (
<div key={match.id} className="flex gap-8 items-center">
<MatchDetailItem
detail={match.players[0]}
isProfileUser={match.players[0].user.id === userId}
/>
<MatchDetailItem
detail={match.players[1]}
isProfileUser={match.players[1].user.id === userId}
/>
<div className="text-sm">{match.createdAt}</div>
</div>
);
})}
</div>
</div>
);
}
5 changes: 3 additions & 2 deletions frontend/app/user/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AcceptFriendButton from "@/app/ui/user/accept-friend-request-button";
import AddFriendButton from "@/app/ui/user/add-friend-button";
import { Avatar } from "@/app/ui/user/avatar";
import CancelFriendRequestButton from "@/app/ui/user/cancel-friend-request-button";
import MatchHistory from "@/app/ui/user/match-history";
import MatchRequestButton from "@/app/ui/user/match-request-button";
import RejectFriendButton from "@/app/ui/user/reject-friend-request-button";
import RemoveFriendButton from "@/app/ui/user/remove-friend-button";
Expand Down Expand Up @@ -36,7 +37,7 @@ export default async function FindUser({
<div>
<Avatar avatarURL={user.avatarURL} size="large" />
</div>
<div className="text-xl font-bold">{user.name}</div>
<div className="text-3xl font-bold">{user.name}</div>
{user.id !== currentUserId && (
<>
<div className="flex gap-4">
Expand All @@ -49,7 +50,7 @@ export default async function FindUser({
<MatchRequestButton id={userId} />
</>
)}
<div className="bg-secondary">Match History</div>
<MatchHistory userId={userId} />
<div className="bg-secondary">Friends</div>
</div>
);
Expand Down

0 comments on commit 2854926

Please sign in to comment.