import { formatDistance } from "date-fns"; import type { LoaderFunction } from "react-router"; import { getUser } from "~/features/auth/core/user.server"; import { nextNonCompletedVoting, rangeToMonthYear, } from "~/features/plus-voting/core"; import { isVotingActive } from "~/features/plus-voting/core/voting-time"; import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server"; 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; 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 (!isVotingActive()) { return { type: "timeInfo", timeInfo: { relativeTime: formatDistance(nextVotingRange.startDate, now, { addSuffix: true, }), timestamp: nextVotingRange.startDate.getTime(), timing: "starts", }, }; } const usersForVoting = user?.plusTier ? await PlusVotingRepository.usersForVoting({ 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", }, }; } return { type: "voting", usersForVoting, votingEnds: { timestamp: nextVotingRange.endDate.getTime(), relativeTime: formatDistance(nextVotingRange.endDate, now, { addSuffix: true, }), }, }; };