mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-02 08:07:40 -05:00
Move app to apps/web-react in pnpm workspace layout
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import { formatDistance } from "date-fns";
|
||||
import type { LoaderFunction } from "react-router";
|
||||
import * as R from "remeda";
|
||||
import { getUser } from "~/features/auth/core/user.server";
|
||||
import {
|
||||
nextNonCompletedVoting,
|
||||
rangeToMonthYear,
|
||||
} from "~/features/plus-voting/core";
|
||||
import { isVotingOpen } from "~/features/plus-voting/core/voting-time";
|
||||
import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
|
||||
import * as UserCardRepository from "~/features/user-card/UserCardRepository.server";
|
||||
import type { UserCardData } from "~/features/user-card/user-card-types";
|
||||
|
||||
export type PlusVotingLoaderData =
|
||||
// next voting date is not in the system
|
||||
| {
|
||||
type: "noTimeDefinedInfo";
|
||||
}
|
||||
// voting is not active OR user is not eligible to vote
|
||||
| {
|
||||
type: "timeInfo";
|
||||
voted?: boolean;
|
||||
timeInfo: {
|
||||
timestamp: number;
|
||||
timing: "starts" | "ends";
|
||||
relativeTime: string;
|
||||
};
|
||||
}
|
||||
// user can vote
|
||||
| {
|
||||
type: "voting";
|
||||
usersForVoting: PlusVotingRepository.UsersForVoting;
|
||||
userCards: Map<number, UserCardData>;
|
||||
votingEnds: {
|
||||
timestamp: number;
|
||||
relativeTime: string;
|
||||
};
|
||||
};
|
||||
|
||||
export const loader: LoaderFunction = async () => {
|
||||
const user = getUser();
|
||||
|
||||
const now = new Date();
|
||||
const nextVotingRange = nextNonCompletedVoting(now);
|
||||
|
||||
if (!nextVotingRange) {
|
||||
return { type: "noTimeDefinedInfo" };
|
||||
}
|
||||
|
||||
if (!isVotingOpen()) {
|
||||
return {
|
||||
type: "timeInfo",
|
||||
timeInfo: {
|
||||
relativeTime: formatDistance(nextVotingRange.startDate, now, {
|
||||
addSuffix: true,
|
||||
}),
|
||||
timestamp: nextVotingRange.startDate.getTime(),
|
||||
timing: "starts",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const usersForVoting = user?.plusTier
|
||||
? await PlusVotingRepository.findAllUsersForVoting({
|
||||
id: user.id,
|
||||
plusTier: user.plusTier,
|
||||
})
|
||||
: undefined;
|
||||
const hasVoted = user
|
||||
? await PlusVotingRepository.hasVoted({
|
||||
authorId: user.id,
|
||||
...rangeToMonthYear(nextVotingRange),
|
||||
})
|
||||
: false;
|
||||
|
||||
if (!usersForVoting || hasVoted) {
|
||||
return {
|
||||
type: "timeInfo",
|
||||
voted: hasVoted,
|
||||
timeInfo: {
|
||||
relativeTime: formatDistance(nextVotingRange.endDate, now, {
|
||||
addSuffix: true,
|
||||
}),
|
||||
timestamp: nextVotingRange.endDate.getTime(),
|
||||
timing: "ends",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const cardUserIds = R.unique(
|
||||
usersForVoting.flatMap(({ user, suggestion }) => [
|
||||
user.id,
|
||||
...(suggestion?.entries ?? []).map((entry) => entry.author.id),
|
||||
]),
|
||||
);
|
||||
|
||||
return {
|
||||
type: "voting",
|
||||
usersForVoting,
|
||||
...(await UserCardRepository.findAllByUserIds({ userIds: cardUserIds })),
|
||||
votingEnds: {
|
||||
timestamp: nextVotingRange.endDate.getTime(),
|
||||
relativeTime: formatDistance(nextVotingRange.endDate, now, {
|
||||
addSuffix: true,
|
||||
}),
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user