import clsx from "clsx"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import type { GearType, Tables, UserWithPlusTier } from "~/db/tables"; import { useUser } from "~/features/auth/core/user"; import type { BuildWeaponWithTop500Info } from "~/features/builds/builds-types"; import { useIsMounted } from "~/hooks/useIsMounted"; import type { Ability as AbilityType, BuildAbilitiesTuple, ModeShort, } from "~/modules/in-game-lists/types"; import { altWeaponIdToId } from "~/modules/in-game-lists/weapon-ids"; import { databaseTimestampToDate } from "~/utils/dates"; import { gearTypeToInitial } from "~/utils/strings"; import { analyzerPage, gearImageUrl, mainWeaponImageUrl, modeImageUrl, mySlugify, navIconUrl, userBuildsPage, weaponBuildPage, } from "~/utils/urls"; import { Ability } from "./Ability"; import styles from "./BuildCard.module.css"; import { LinkButton, SendouButton } from "./elements/Button"; import { SendouPopover } from "./elements/Popover"; import { FormWithConfirm } from "./FormWithConfirm"; import { Image } from "./Image"; import { EditIcon } from "./icons/Edit"; import { LockIcon } from "./icons/Lock"; import { SpeechBubbleIcon } from "./icons/SpeechBubble"; import { TrashIcon } from "./icons/Trash"; interface BuildProps { build: Pick< Tables["Build"], | "id" | "title" | "description" | "clothesGearSplId" | "headGearSplId" | "shoesGearSplId" | "updatedAt" | "private" > & { abilities: BuildAbilitiesTuple; modes: ModeShort[] | null; weapons: Array; }; owner?: Pick; canEdit?: boolean; } export function BuildCard({ build, owner, canEdit = false }: BuildProps) { const user = useUser(); const { t } = useTranslation(["weapons", "builds", "common", "game-misc"]); const { i18n } = useTranslation(); const isMounted = useIsMounted(); const { id, title, description, clothesGearSplId, headGearSplId, shoesGearSplId, updatedAt, modes, weapons, abilities, } = build; const isNoGear = [headGearSplId, clothesGearSplId, shoesGearSplId].some( (id) => id === -1, ); return (
{modes && modes.length > 0 && (
{modes.map((mode) => ( {t(`game-misc:MODE_LONG_${mode}` ))}
)}

{title}

{owner && ( <> {owner.username}
)} {owner?.plusTier ? ( <> +{owner.plusTier}
) : null}
{build.private ? (
{" "} {t("common:build.private")}
) : null}
{weapons.map((weapon) => ( ))} {weapons.length === 1 && (
{t(`weapons:MAIN_${weapons[0].weaponSplId}` as any)}
)}
{t("common:pages.analyzer")} {description ? ( } className={styles.smallText} /> } > {description} ) : null} {canEdit && ( <> } className={styles.smallText} variant="minimal-destructive" type="submit" /> )}
); } function RoundWeaponImage({ weapon }: { weapon: BuildWeaponWithTop500Info }) { const normalizedWeaponSplId = altWeaponIdToId.get(weapon.weaponSplId) ?? weapon.weaponSplId; const { t } = useTranslation(["weapons"]); const slug = mySlugify( t(`weapons:MAIN_${normalizedWeaponSplId}`, { lng: "en" }), ); return (
{weapon.isTop500 ? ( ) : null} {t(`weapons:MAIN_${weapon.weaponSplId}`)}
); } function AbilitiesRowWithGear({ gearType, abilities, gearId, }: { gearType: GearType; abilities: AbilityType[]; gearId: number; }) { const { t } = useTranslation(["gear"]); const translatedGearName = t( `gear:${gearTypeToInitial(gearType)}_${gearId}` as any, ); return ( <> {gearId !== -1 ? ( {translatedGearName} ) : null} {abilities.map((ability, i) => ( ))} ); }