sendou.ink/app/features/lfg/actions/lfg.new.server.ts
Kalle 4beb2bdfdd
LFG (#1732)
* Initial

* Can post new

* Load team

* seed + loader posts

* LFGPost render initial

* More UI work

* Tiers

* sticky left

* Mobile

* new.tsx work

* TeamLFGPost component initial

* Full team member list

* Add TODO

* Delete post action

* Edit post etc.

* Delete team posts when team disbands

* Prevent adding same post type twice in UI

* Post expiry logic

* Fix layout shift

* Filters initial

* Progress

* Weapon filtered implemented

* Weapon alt kits in filtering

* + visibility

* i18n

* E2E test

* Team = null
2024-05-19 13:43:59 +03:00

79 lines
2.3 KiB
TypeScript

import { z } from "zod";
import { TEAM_POST_TYPES, LFG, TIMEZONES } from "../lfg-constants";
import type { ActionFunctionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import { requireUser } from "~/features/auth/core/user.server";
import { parseRequestFormData, validate } from "~/utils/remix";
import { LFG_PAGE } from "~/utils/urls";
import * as LFGRepository from "../LFGRepository.server";
import * as UserRepository from "~/features/user-page/UserRepository.server";
import { falsyToNull, id } from "~/utils/zod";
export const action = async ({ request }: ActionFunctionArgs) => {
const user = await requireUser(request);
const data = await parseRequestFormData({
request,
schema,
});
const identifier = String(user.id);
const { team } = (await UserRepository.findByIdentifier(identifier)) ?? {};
const shouldIncludeTeam = TEAM_POST_TYPES.includes(data.type);
validate(
!shouldIncludeTeam || team,
"Team needs to be set for this type of post",
);
if (data.postId) {
await validateCanUpdatePost({
postId: data.postId,
user,
});
await LFGRepository.updatePost(data.postId, {
text: data.postText,
timezone: data.timezone,
type: data.type,
teamId: shouldIncludeTeam ? team?.id : null,
plusTierVisibility: data.plusTierVisibility,
});
} else {
await LFGRepository.insertPost({
text: data.postText,
timezone: data.timezone,
type: data.type,
teamId: shouldIncludeTeam ? team?.id : null,
authorId: user.id,
plusTierVisibility: data.plusTierVisibility,
});
}
return redirect(LFG_PAGE);
};
const schema = z.object({
postId: id.optional(),
type: z.enum(LFG.types),
postText: z.string().min(LFG.MIN_TEXT_LENGTH).max(LFG.MAX_TEXT_LENGTH),
timezone: z.string().refine((val) => TIMEZONES.includes(val)),
plusTierVisibility: z.preprocess(
falsyToNull,
z.coerce.number().int().min(1).max(3).nullish(),
),
});
const validateCanUpdatePost = async ({
postId,
user,
}: {
postId: number;
user: { id: number; plusTier: number | null };
}) => {
const posts = await LFGRepository.posts(user);
const post = posts.find((post) => post.id === postId);
validate(post, "Post to update not found");
validate(post.author.id === user.id, "You can only update your own posts");
};