mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-06-02 22:26:57 -05:00
Match over info UI
This commit is contained in:
parent
3913eea1a9
commit
4f4473b355
|
|
@ -21,9 +21,7 @@ interface MapListProps {
|
|||
};
|
||||
}
|
||||
export function MapList({ mapList, canSubmitScore, groupIds }: MapListProps) {
|
||||
const [winners, setWinners] = useState<string[]>(
|
||||
new Array(5).fill(null).map(() => "5f31654d-977b-402b-817a-6f20cd933aa5")
|
||||
);
|
||||
const [winners, setWinners] = useState<string[]>([]);
|
||||
|
||||
const updateWinners = (winnerId: string, index: number) => {
|
||||
const newWinners = clone(winners);
|
||||
|
|
|
|||
|
|
@ -24,20 +24,20 @@ export function findById(id: string) {
|
|||
}
|
||||
|
||||
export function reportScore({
|
||||
matchId,
|
||||
winnerIds,
|
||||
UNSAFE_matchId,
|
||||
UNSAFE_winnerIds,
|
||||
}: {
|
||||
matchId: string;
|
||||
winnerIds: string[];
|
||||
UNSAFE_matchId: string;
|
||||
UNSAFE_winnerIds: string[];
|
||||
}) {
|
||||
// https://stackoverflow.com/a/26715934
|
||||
return db.$executeRawUnsafe(`
|
||||
update "LfgGroupMatchStage" as lfg set
|
||||
"winnerGroupId" = lfg2.winner_id
|
||||
from (values
|
||||
${winnerIds
|
||||
.map((winnerId, i) => `('${matchId}', ${i + 1}, '${winnerId}')`)
|
||||
.join(",")}
|
||||
${UNSAFE_winnerIds.map(
|
||||
(winnerId, i) => `('${UNSAFE_matchId}', ${i + 1}, '${winnerId}')`
|
||||
).join(",")}
|
||||
) as lfg2(lfg_group_match_id, "order", winner_id)
|
||||
where lfg2.lfg_group_match_id = lfg."lfgGroupMatchId" and lfg2.order = lfg.order;
|
||||
`);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { Mode } from "@prisma/client";
|
||||
import clsx from "clsx";
|
||||
import {
|
||||
ActionFunction,
|
||||
Form,
|
||||
|
|
@ -14,6 +15,8 @@ import invariant from "tiny-invariant";
|
|||
import { z } from "zod";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import { Button } from "~/components/Button";
|
||||
import { CheckmarkIcon } from "~/components/icons/Checkmark";
|
||||
import { ModeImage } from "~/components/ModeImage";
|
||||
import { MapList } from "~/components/play/MapList";
|
||||
import { DISCORD_URL } from "~/constants";
|
||||
import * as LFGGroup from "~/models/LFGGroup.server";
|
||||
|
|
@ -75,8 +78,8 @@ export const action: ActionFunction = async ({ request, context }) => {
|
|||
case "REPORT_SCORE": {
|
||||
validate(ownGroup.matchId, "No match for the group");
|
||||
await LFGMatch.reportScore({
|
||||
matchId: ownGroup.matchId,
|
||||
winnerIds: data.winnerIds,
|
||||
UNSAFE_matchId: ownGroup.matchId,
|
||||
UNSAFE_winnerIds: data.winnerIds,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
|
@ -111,7 +114,7 @@ interface LFGMatchLoaderData {
|
|||
winner?: number;
|
||||
}[];
|
||||
/** The final score. Shown if match is concluded */
|
||||
score?: [number, number];
|
||||
scores?: [number, number];
|
||||
}
|
||||
|
||||
export const loader: LoaderFunction = async ({ params, context }) => {
|
||||
|
|
@ -154,7 +157,7 @@ export const loader: LoaderFunction = async ({ params, context }) => {
|
|||
})),
|
||||
};
|
||||
});
|
||||
const score = match.stages[0].winnerGroupId
|
||||
const scores = match.stages[0].winnerGroupId
|
||||
? match.stages.reduce(
|
||||
(acc: [number, number], stage) => {
|
||||
if (!stage.winnerGroupId) return acc;
|
||||
|
|
@ -170,7 +173,7 @@ export const loader: LoaderFunction = async ({ params, context }) => {
|
|||
isRanked,
|
||||
isOwnMatch,
|
||||
groups,
|
||||
score,
|
||||
scores,
|
||||
mapList: match.stages
|
||||
.map(({ stage, winnerGroupId }) => {
|
||||
const winner = () => {
|
||||
|
|
@ -183,7 +186,7 @@ export const loader: LoaderFunction = async ({ params, context }) => {
|
|||
winner: winner(),
|
||||
};
|
||||
})
|
||||
.filter((stage) => !score || typeof stage.winner === "number"),
|
||||
.filter((stage) => !scores || typeof stage.winner === "number"),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -199,7 +202,7 @@ export default function LFGMatchPage() {
|
|||
return (
|
||||
<div
|
||||
key={i}
|
||||
className="play-match__waves-section play-match__players"
|
||||
className="play-match__waves-section play-match__team-info"
|
||||
>
|
||||
{g.members.map((user) => (
|
||||
<div key={user.id} className="play-match__player">
|
||||
|
|
@ -209,6 +212,15 @@ export default function LFGMatchPage() {
|
|||
</span>
|
||||
</div>
|
||||
))}
|
||||
{data.scores && (
|
||||
<div
|
||||
className={clsx("play-match__score", {
|
||||
winner: data.scores[i] === Math.max(...data.scores),
|
||||
})}
|
||||
>
|
||||
{data.scores[i]}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
|
@ -220,6 +232,37 @@ export default function LFGMatchPage() {
|
|||
<code>#match-meetup</code> channel.
|
||||
</div>
|
||||
)}
|
||||
{data.scores && (
|
||||
<div className="play-match__played-map-list">
|
||||
{data.mapList.map((stage) => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={clsx("play-match__checkmark", "left", {
|
||||
invisible: stage.winner === 0,
|
||||
})}
|
||||
>
|
||||
<CheckmarkIcon />
|
||||
</div>
|
||||
<div className="play-match__played-stage">
|
||||
<ModeImage
|
||||
className="play-match__played-mode"
|
||||
mode={stage.mode}
|
||||
/>
|
||||
{stage.name}
|
||||
</div>
|
||||
<div
|
||||
className={clsx("play-match__checkmark", {
|
||||
invisible: stage.winner === 1,
|
||||
})}
|
||||
>
|
||||
<CheckmarkIcon />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!data.isRanked && (
|
||||
<div className="play-match__waves-button">
|
||||
|
|
@ -239,7 +282,7 @@ export default function LFGMatchPage() {
|
|||
</Form>
|
||||
</div>
|
||||
)}
|
||||
{!data.score && (
|
||||
{!data.scores && (
|
||||
<MapList
|
||||
mapList={data.mapList}
|
||||
canSubmitScore={data.isCaptain}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,42 @@
|
|||
margin-block-start: var(--s-8);
|
||||
}
|
||||
|
||||
.play-match__players {
|
||||
.play-match__played-map-list {
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
font-size: var(--fonts-sm);
|
||||
font-weight: var(--semi-bold);
|
||||
gap: var(--s-2);
|
||||
grid-template-columns: 4rem max-content 4rem;
|
||||
margin-block-start: var(--s-4);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.play-match__checkmark {
|
||||
display: grid;
|
||||
width: 2rem;
|
||||
color: var(--theme-success);
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.play-match__checkmark.left {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.play-match__played-stage {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: var(--s-1);
|
||||
background-color: var(--bg-darker);
|
||||
border-radius: var(--rounded);
|
||||
}
|
||||
|
||||
.play-match__played-mode {
|
||||
width: 1.5rem;
|
||||
}
|
||||
|
||||
.play-match__team-info {
|
||||
display: grid;
|
||||
max-width: 14rem;
|
||||
flex: 1;
|
||||
|
|
@ -46,6 +81,17 @@
|
|||
font-size: var(--fonts-xs);
|
||||
}
|
||||
|
||||
.play-match__score {
|
||||
border-radius: var(--rounded);
|
||||
font-size: var(--fonts-lg);
|
||||
font-weight: var(--bold);
|
||||
grid-column: 1 / 3;
|
||||
}
|
||||
|
||||
.play-match__score.winner {
|
||||
background-color: var(--theme-transparent);
|
||||
}
|
||||
|
||||
.play-match__waves-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user