Skip to content

Commit

Permalink
Controlled demand in construction
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-hanzal committed Jan 31, 2025
1 parent edfd4fc commit 23c0923
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ export const Route = createFileRoute(
"/$locale/apps/derivean/map/$mapId/building/$buildingId/view",
)({
async loader({
context: { queryClient, kysely },
context: { queryClient, kysely, session },
params: { mapId, buildingId },
}) {
const user = await session();

return {
user,
requirement: await queryClient.ensureQueryData({
queryKey: [
"GameMap",
Expand Down Expand Up @@ -88,6 +91,19 @@ export const Route = createFileRoute(
.limit(1)
.as("available");
},
(eb) => {
return eb
.selectFrom("Demand as d")
.select((eb) => {
return Kysely.jsonObject({
id: eb.ref("d.id"),
priority: eb.ref("d.priority"),
}).as("demand");
})
.whereRef("d.resourceId", "=", "br.resourceId")
.where("d.buildingId", "=", buildingId)
.as("demand");
},
])
.orderBy("r.name", "asc"),
output: z.object({
Expand All @@ -103,6 +119,12 @@ export const Route = createFileRoute(
name: z.string().min(1),
}),
).nullish(),
demand: withJsonSchema(
z.object({
id: z.string().min(1),
priority: z.number(),
}),
).nullish(),
passive: withBoolSchema(),
}),
});
Expand All @@ -115,10 +137,11 @@ export const Route = createFileRoute(
const { building } = useLoaderData({
from: "/$locale/apps/derivean/map/$mapId/building/$buildingId",
});
const { requirement } = Route.useLoaderData();
const { user, requirement } = Route.useLoaderData();

return building.constructionId ?
<RequirementPanel
userId={user.id}
building={building}
requirement={requirement}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,76 @@
import { Icon, Progress } from "@use-pico/client";
import { useMutation } from "@tanstack/react-query";
import {
ArrowDownIcon,
ArrowUpIcon,
Badge,
Button,
Icon,
Progress,
Tx,
useInvalidator,
} from "@use-pico/client";
import { toHumanNumber, tvc } from "@use-pico/common";
import type { FC } from "react";
import { kysely } from "~/app/derivean/db/kysely";
import type { RequirementPanel } from "~/app/derivean/game/GameMap2/Construction/Requirement/RequirementPanel";
import { DemandIcon } from "~/app/derivean/icon/DemandIcon";
import { PackageIcon } from "~/app/derivean/icon/PackageIcon";

export namespace Item {
export interface Props {
mapId: string;
userId: string;
requirement: RequirementPanel.Requirement;
}
}

export const Item: FC<Item.Props> = ({ requirement }) => {
export const Item: FC<Item.Props> = ({ mapId, userId, requirement }) => {
const invalidator = useInvalidator([["GameMap"]]);
const available = requirement.available || 0;
const priorityUpMutation = useMutation({
async mutationFn({ demandId }: { demandId: string }) {
return kysely.transaction().execute(async (tx) => {
const { priority } = await tx
.selectFrom("Demand as d")
.select((eb) => eb.fn.max("d.priority").as("priority"))
.where("d.mapId", "=", mapId)
.where("d.userId", "=", userId)
.where("d.id", "!=", demandId)
.executeTakeFirstOrThrow();

return tx
.updateTable("Demand")
.set({ priority: priority + 1 })
.where("id", "=", demandId)
.execute();
});
},
async onSuccess() {
await invalidator();
},
});
const priorityDownMutation = useMutation({
async mutationFn({ demandId }: { demandId: string }) {
return kysely.transaction().execute(async (tx) => {
const { priority } = await tx
.selectFrom("Demand as d")
.select((eb) => eb.fn.min("d.priority").as("priority"))
.where("d.mapId", "=", mapId)
.where("d.userId", "=", userId)
.where("d.id", "!=", demandId)
.executeTakeFirstOrThrow();

return tx
.updateTable("Demand")
.set({ priority: priority - 1 })
.where("id", "=", demandId)
.execute();
});
},
async onSuccess() {
await invalidator();
},
});

return (
<div
Expand Down Expand Up @@ -84,6 +142,48 @@ export const Item: FC<Item.Props> = ({ requirement }) => {
available >= requirement.amount ? ["bg-green-500"] : undefined,
}}
/>

{requirement.demand ?
<div
className={"flex flex-row gap-2 items-center justify-between w-full"}
>
<Button
iconEnabled={ArrowUpIcon}
variant={{ variant: "subtle" }}
loading={
priorityUpMutation.isPending || priorityDownMutation.isPending
}
onClick={() => {
requirement.demand &&
priorityUpMutation.mutate({ demandId: requirement.demand.id });
}}
>
<Tx label={"Priority up (label)"} />
</Button>
<Badge
css={{
base: ["bg-purple-50", "border-purple-400", "text-purple-600"],
}}
>
{requirement.demand.priority}
</Badge>
<Button
iconEnabled={ArrowDownIcon}
variant={{ variant: "subtle" }}
loading={
priorityUpMutation.isPending || priorityDownMutation.isPending
}
onClick={() => {
requirement.demand &&
priorityDownMutation.mutate({
demandId: requirement.demand.id,
});
}}
>
<Tx label={"Priority down (label)"} />
</Button>
</div>
: null}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,31 @@ export namespace RequirementPanel {
id: string;
}

export interface Demand {
id: string;
priority: number;
}

export interface Requirement {
id: string;
name: string;
amount: number;
transport: number;
supply?: Supply | null;
available?: number | null;
demand?: Demand | null;
passive: boolean;
}

export interface Props extends Panel.PropsEx {
userId: string;
building: Building;
requirement: Requirement[];
}
}

export const RequirementPanel: FC<RequirementPanel.Props> = ({
userId,
building,
requirement,
...props
Expand Down Expand Up @@ -61,6 +69,8 @@ export const RequirementPanel: FC<RequirementPanel.Props> = ({
return (
<Item
key={item.id}
mapId={mapId}
userId={userId}
requirement={item}
/>
);
Expand Down

0 comments on commit 23c0923

Please sign in to comment.