Skip to content

Commit

Permalink
feat(v2): optimized room-state implementation
Browse files Browse the repository at this point in the history
Cleaner implementation which helps with better typescript typings.
  • Loading branch information
jkrumm committed Jan 19, 2024
1 parent 07da824 commit 3f6b30f
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 196 deletions.
13 changes: 8 additions & 5 deletions src/components/room/interactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RouteType } from "fpp/server/db/schema";
import { useRoomStateStore } from "fpp/store/room-state.store";
import { useLocalstorageStore } from "fpp/store/local-storage.store";
import { api } from "fpp/utils/api";
import { roomStateStatus } from "fpp/server/room-state/room-state.entity";

export const Interactions = ({
roomId,
Expand Down Expand Up @@ -37,7 +38,7 @@ export const Interactions = ({
const leaveMutation = api.roomState.leave.useMutation();

// Room state
const isFlipped = useRoomStateStore((store) => store.isFlipped);
const status = useRoomStateStore((store) => store.status);
const resetMutation = api.roomState.reset.useMutation();
const isAutoFlip = useRoomStateStore((store) => store.isAutoFlip);
const autoFlipMutation = api.roomState.autoFlip.useMutation();
Expand Down Expand Up @@ -92,7 +93,9 @@ export const Interactions = ({
</Button>
<div>
<Button
variant={isFlipped ? "filled" : "default"}
variant={
status === roomStateStatus.flipped ? "filled" : "default"
}
className={"mr-5"}
onClick={() => {
resetMutation.mutate({
Expand All @@ -101,7 +104,7 @@ export const Interactions = ({
});
}}
>
{isFlipped ? "New Round" : "Reset"}
{status === roomStateStatus.flipped ? "New Round" : "Reset"}
</Button>
<Button
variant={"default"}
Expand Down Expand Up @@ -133,7 +136,7 @@ export const Interactions = ({
<Button.Group className="w-full">
{fibonacciSequence.map((number) => (
<Button
disabled={isSpectator || isFlipped}
disabled={isSpectator || status === roomStateStatus.flipped}
variant={estimation === number ? "filled" : "default"}
size={"lg"}
fullWidth
Expand All @@ -155,7 +158,7 @@ export const Interactions = ({
<div className="switch-bar">
<Switch
className="mb-2 cursor-pointer"
disabled={isFlipped}
disabled={status === roomStateStatus.flipped}
label="Spectator"
checked={isSpectator}
onChange={(event) => {
Expand Down
123 changes: 75 additions & 48 deletions src/components/room/table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import { api } from "fpp/utils/api";
import { type Logger } from "next-axiom";
import { useRoomStateStore } from "fpp/store/room-state.store";
import { Button } from "@mantine/core";
import {
roomStateStatus,
type User,
} from "fpp/server/room-state/room-state.entity";
import {
getAverageFromUsers,
getStackedEstimationsFromUsers,
} from "fpp/server/room-state/room-state.utils";

export const Table = ({
roomId,
Expand All @@ -16,57 +24,22 @@ export const Table = ({
logger: Logger;
}) => {
const users = useRoomStateStore((store) => store.users);
const isFlipped = useRoomStateStore((store) => store.isFlipped);
const isFlippable = useRoomStateStore((store) => store.isFlippable);
const averageEstimation = useRoomStateStore(
(store) => store.averageEstimation,
);
const stackedEstimations = useRoomStateStore(
(store) => store.stackedEstimations,
);

const flipMutation = api.roomState.flip.useMutation();
const status = useRoomStateStore((store) => store.status);

return (
<div className="table">
<div className="card-place">
{isFlipped && (
<>
{stackedEstimations.slice(0, 4).map((item, index) => (
<div key={index} className={`card-wrapper amount-${item.amount}`}>
{(function () {
const cards = [];
for (let i = 0; i < item.amount; i++) {
cards.push(
<div className="card" key={i}>
{item.number}
</div>,
);
}
return cards;
})()}
</div>
))}
<div className="average">{averageEstimation}</div>
</>
)}
{!isFlipped && !isFlippable && <div className="vote">VOTE</div>}
{!isFlipped && isFlippable && (
<div className="relative flex h-full w-full items-center justify-center">
<Button
size="lg"
className="center"
onClick={() => {
flipMutation.mutate({
roomId,
userId,
});
}}
>
Show Votes
</Button>
</div>
)}
{(function () {
switch (status) {
case roomStateStatus.flipped:
return <StackedEstimations users={users} />;
case roomStateStatus.flippable:
return <ShowVotesButton roomId={roomId} userId={userId} />;
case roomStateStatus.estimating:
default:
return <div className="vote">VOTE</div>;
}
})()}
</div>

<div className="players">
Expand All @@ -76,7 +49,11 @@ export const Table = ({
<div className={`name ${user.id === userId && "font-bold"}`}>
{user.name}
</div>
<div className={`card ${isFlipped && "flipped"} ${user.status}`}>
<div
className={`card ${roomStateStatus.flipped && "flipped"} ${
user.status
}`}
>
{user.estimation}
</div>
</div>
Expand All @@ -85,3 +62,53 @@ export const Table = ({
</div>
);
};

function StackedEstimations({ users }: { users: User[] }) {
return (
<>
{getStackedEstimationsFromUsers(users).map((item, index) => (
<div key={index} className={`card-wrapper amount-${item.amount}`}>
{(function () {
const cards = [];
for (let i = 0; i < item.amount; i++) {
cards.push(
<div className="card" key={i}>
{item.number}
</div>,
);
}
return cards;
})()}
</div>
))}
<div className="average">{getAverageFromUsers(users)}</div>
</>
);
}

function ShowVotesButton({
roomId,
userId,
}: {
roomId: number;
userId: string;
}) {
const flipMutation = api.roomState.flip.useMutation();

return (
<div className="relative flex h-full w-full items-center justify-center">
<Button
size="lg"
className="center"
onClick={() => {
flipMutation.mutate({
roomId,
userId,
});
}}
>
Show Votes
</Button>
</div>
);
}
4 changes: 2 additions & 2 deletions src/hooks/use-room-state.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export const useRoomState = ({
isSpectator,
},
{
onSuccess: (roomStateJson) => {
updateRoomState(RoomStateClient.fromJson(roomStateJson));
onSuccess: (roomStateDto) => {
updateRoomState(RoomStateClient.fromJson(roomStateDto));
setIsConnecting(false);
},
},
Expand Down
4 changes: 2 additions & 2 deletions src/pages/api/trpc/[trpc].ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ const trpcErrorHandler = ({
});

if (env.NEXT_PUBLIC_NODE_ENV === "production") {
return new TRPCError({
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Internal Server Error",
});
} else {
return error;
throw error;
}
}
console.warn("TRPC ERROR", { ...inputObj, ...errorObj });
Expand Down
13 changes: 7 additions & 6 deletions src/server/api/routers/contact.router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createTRPCRouter, publicProcedure } from "fpp/server/api/trpc";
import { z } from "zod";
import { featureFlags, FeatureFlagType } from "fpp/server/db/schema";
import { eq } from "drizzle-orm";
import { NotImplementedError } from "fpp/constants/error.constant";
import { TRPCError } from "@trpc/server";

export const contactRouter = createTRPCRouter({
sendMail: publicProcedure
Expand All @@ -19,11 +19,12 @@ export const contactRouter = createTRPCRouter({
.select()
.from(featureFlags)
.where(eq(featureFlags.name, FeatureFlagType.CONTACT_FORM))
.get();
if (!featureFlagEntry?.enabled) {
throw new NotImplementedError(
"CONTACT_FORM feature flag is not enabled",
);
.execute();
if (!featureFlagEntry[0]?.enabled) {
throw new TRPCError({
message: "CONTACT_FORM feature flag is not enabled",
code: "NOT_IMPLEMENTED",
});
}

// const mailData = {
Expand Down
Loading

0 comments on commit 3f6b30f

Please sign in to comment.