Introduced classes for weapons and agents and restructured code

This commit is contained in:
2026-09-12 00:56:08 +02:00
parent 8400ec7632
commit dc9b69b42d
4 changed files with 103 additions and 98 deletions

View File

@@ -1,25 +1,16 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Skeleton, Surface } from "@heroui/react"; import { Skeleton, Surface } from "@heroui/react";
import { Agent } from "./agent"; import { Agent } from "./agent";
import { Weapon } from "./weapon"; import { SkinTile } from "./skin_tile";
import { useNotification } from "~/hooks/notification"; import { useNotification } from "~/hooks/notification";
import { WeaponInfo, AgentInfo } from "~/types/skin";
interface SkinInfo {
id: string;
name: string;
color: string;
display: string;
paint_index: number;
float: number;
pattern: number;
}
export function Inventory({ side }: { side: "T" | "CT" }) { export function Inventory({ side }: { side: "T" | "CT" }) {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [agent, setAgent] = useState<SkinInfo>(); const [agent, setAgent] = useState<AgentInfo>();
const [gloves, setGloves] = useState<SkinInfo>(); const [gloves, setGloves] = useState<WeaponInfo>();
const [knife, setKnife] = useState<SkinInfo>(); const [knife, setKnife] = useState<WeaponInfo>();
const [weapons, setWeapons] = useState<Array<SkinInfo>>([]); const [weapons, setWeapons] = useState<Array<WeaponInfo>>([]);
const { notify } = useNotification(); const { notify } = useNotification();
useEffect(() => { useEffect(() => {
@@ -41,7 +32,7 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
); );
}); });
setKnife(response[0]); setKnife(new WeaponInfo(response[0]));
response = await fetch( response = await fetch(
`${import.meta.env.VITE_BASE_API_URL}/skin?team=${side}&category=Gloves`, `${import.meta.env.VITE_BASE_API_URL}/skin?team=${side}&category=Gloves`,
@@ -60,7 +51,7 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
); );
}); });
setGloves(response[0]); setGloves(new WeaponInfo(response[0]));
response = await fetch( response = await fetch(
`${import.meta.env.VITE_BASE_API_URL}/skin?team=${side}`, `${import.meta.env.VITE_BASE_API_URL}/skin?team=${side}`,
@@ -79,7 +70,7 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
); );
}); });
setWeapons(response); setWeapons(response.map((item: any) => (new WeaponInfo(item))));
response = await fetch( response = await fetch(
`${import.meta.env.VITE_BASE_API_URL}/agent?team=${side}`, `${import.meta.env.VITE_BASE_API_URL}/agent?team=${side}`,
@@ -98,7 +89,7 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
); );
}); });
setAgent(response); setAgent(new AgentInfo(response));
setLoading(false); setLoading(false);
}; };
@@ -149,31 +140,19 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
{agent && <Agent agent_id={agent["name"]}></Agent>} {agent && <Agent agent_id={agent["name"]}></Agent>}
<div className="flex gap-2"> <div className="flex gap-2">
{knife && ( {knife && (
<Weapon <SkinTile
weapon_id={knife["name"]} skin={knife}
color={knife["color"]} ></SkinTile>
paint_index={knife["paint_index"]}
display={knife["display"]}
float={knife["float"]}
pattern={knife["pattern"]}
></Weapon>
)} )}
{gloves && ( {gloves && (
<Weapon <SkinTile
weapon_id={gloves["name"]} skin={gloves}
color={gloves["color"]} ></SkinTile>
paint_index={gloves["paint_index"]}
display={gloves["display"]}
float={gloves["float"]}
pattern={gloves["pattern"]}
></Weapon>
)} )}
{agent && ( {agent && (
<Weapon <SkinTile
weapon_id={agent["name"]} skin={agent}
color={agent["color"]} ></SkinTile>
display={agent["display"]}
></Weapon>
)} )}
</div> </div>
</Surface> </Surface>
@@ -183,14 +162,9 @@ export function Inventory({ side }: { side: "T" | "CT" }) {
> >
<div className="absolute inset-4 flex-1 grid grid-cols-5 gap-2 overflow-y-scroll"> <div className="absolute inset-4 flex-1 grid grid-cols-5 gap-2 overflow-y-scroll">
{weapons.map((v, i) => ( {weapons.map((v, i) => (
<Weapon <SkinTile
key={i} key={i}
weapon_id={v.name} skin={v}
color={v.color}
paint_index={v.paint_index}
display={v.display}
float={v.float}
pattern={v.pattern}
/> />
))} ))}
</div> </div>

View File

@@ -0,0 +1,58 @@
import { Button, Typography } from "@heroui/react";
import { Float } from "./float";
import { useState } from "react";
import { SkinDialog } from "./skin_dialog";
import { WeaponInfo, AgentInfo } from "~/types/skin";
export function SkinTile({ skin }: { skin: WeaponInfo | AgentInfo }) {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const acolor = `${skin.color}64`;
return (
<>
<SkinDialog
isOpen={isDialogOpen}
setIsOpen={setIsDialogOpen}
skin={skin}
/>
<Button
onClick={() => setIsDialogOpen(true)}
className="bg-mist-700 flex flex-col h-full p-0 rounded-none gap-0 hover:bg-indigo-800 active:bg-indigo-900"
>
<div className="flex flex-col w-full h-full">
<div
className="bg-linear-to-b pointer-events-none w-full h-full"
style={{
background: `linear-gradient(to bottom, #1f2937, ${acolor})`,
}}
>
<img
src={`/skins/${skin.name}_${skin instanceof WeaponInfo ? skin.paint_index : 0}.png`}
className="pointer-events-none object-contain object-bottom h-full"
alt="Weapon image"
/>
</div>
<div
className={`h-1 w-full`}
style={{ background: `${skin.color}` }}
></div>
<div className="px-2">
<Typography.Heading
level={6}
className="py-1 text-wrap"
>
{skin.display}
</Typography.Heading>
{skin instanceof WeaponInfo && (
<Float float={skin.float} />
)}
{skin instanceof WeaponInfo && (
<Typography.Paragraph>
Pattern: {skin.pattern}
</Typography.Paragraph>
)}
</div>
</div>
</Button>
</>
);
}

View File

@@ -1,51 +0,0 @@
import { Button, Surface, Typography } from "@heroui/react";
import { Float } from "./float";
export function Weapon({
weapon_id,
color,
display = "Weapon",
float,
pattern,
paint_index = 0,
}: {
weapon_id: string;
color: string;
display?: string;
float?: number;
pattern?: number;
paint_index?: number;
}) {
const acolor = `${color}64`;
return (
<Button className="bg-mist-700 flex flex-col h-full p-0 rounded-none gap-0 hover:bg-indigo-800 active:bg-indigo-900">
<div className="flex flex-col w-full h-full">
<div
className="bg-linear-to-b pointer-events-none w-full h-full"
style={{
background: `linear-gradient(to bottom, #1f2937, ${acolor})`,
}}
>
<img
src={`/skins/${weapon_id}_${paint_index || 0}.png`}
className="pointer-events-none object-contain object-bottom h-full"
alt="Weapon image"
/>
</div>
<div
className={`h-1 w-full`}
style={{ background: `${color}` }}
></div>
<Typography.Heading level={6} className="px-2 py-1 text-wrap">
{display}
</Typography.Heading>
{float !== undefined && <Float float={float} />}
{pattern !== undefined && (
<Typography.Paragraph className="px-2">
Pattern: {pattern}
</Typography.Paragraph>
)}
</div>
</Button>
);
}

24
app/types/skin.ts Normal file
View File

@@ -0,0 +1,24 @@
export class WeaponInfo {
id!: string;
name!: string;
color!: string;
display!: string;
paint_index!: number;
float!: number;
pattern!: number;
constructor(data: WeaponInfo) {
Object.assign(this, data);
}
}
export class AgentInfo {
id!: string;
name!: string;
color!: string;
display!: string;
constructor(data: AgentInfo) {
Object.assign(this, data);
}
}