scrummie-poker/src/lib/context/estimation.tsx
2024-10-11 20:47:24 +03:00

191 lines
4.8 KiB
TypeScript

import {
createContext,
PropsWithChildren,
useContext,
useEffect,
useState,
} from 'react';
import {
client,
DATABASE_ID,
databases,
ESTIMATION_SESSION_COLLECTION_ID,
} from '../appwrite';
import { DatabaseModels, EntityModels } from '../types';
import { useUser } from './user';
import { EstimationSessionTicket } from '../types/entityModels';
interface EstimationContextType {
setSessionId: (sessionId: string) => void;
setActiveTicket: (ticketId: string) => Promise<void>;
setRevealed: (revealed: boolean) => Promise<void>;
setVote: (estimate: string) => Promise<void>;
createTicket: (ticket: Omit<EstimationSessionTicket, 'id'>) => Promise<void>;
currentSessionData?: EntityModels.EstimationSession;
}
const EstimationContext = createContext<EstimationContextType | undefined>(
undefined,
);
export const useEstimationContext = () => {
return useContext(EstimationContext);
};
const mapEstimationSession = (
data: DatabaseModels.EstimationSession,
{ userId }: { userId?: string },
) => {
const sessionState: EntityModels.SessionState = data.sessionState
? JSON.parse(data.sessionState)
: {
votes: [],
};
const tickets = data.tickets
? data.tickets.map<EntityModels.EstimationSessionTicket>((ticket) =>
JSON.parse(ticket),
)
: [];
const result: EntityModels.EstimationSession = {
id: data.$id,
name: data.name,
userId: data.userId,
tickets,
sessionState: {
...sessionState,
currentPlayerVote: sessionState.votes.find((x) => x.userId === userId)
?.estimate,
currentTicket: tickets.find((x) => x.id === sessionState.currentTicketId),
},
};
console.log({
result,
userId,
});
return result;
};
export const EstimationContextProvider = (props: PropsWithChildren) => {
const [sessionId, setSessionId] = useState('');
const [currentSessionData, setCurrentSessionData] =
useState<EntityModels.EstimationSession>();
const { current: userData } = useUser();
useEffect(() => {
if (!sessionId || !userData) {
return () => {};
}
databases
.getDocument<DatabaseModels.EstimationSession>(
DATABASE_ID,
ESTIMATION_SESSION_COLLECTION_ID,
sessionId,
)
.then((payload) => {
const userId = userData?.$id ?? ''; // TODO: Not sure if this is the user id or session
setCurrentSessionData(mapEstimationSession(payload, { userId }));
});
return client.subscribe<DatabaseModels.EstimationSession>(
[
`databases.${DATABASE_ID}.collections.${ESTIMATION_SESSION_COLLECTION_ID}.documents.${sessionId}`,
],
({ payload }) => {
const userId = userData?.$id ?? ''; // TODO: Not sure if this is the user id or session
setCurrentSessionData(mapEstimationSession(payload, { userId }));
},
);
}, [sessionId, userData]);
const setSessionIdFunc = (newSessionId: string) => {
if (sessionId !== newSessionId) {
setSessionId(newSessionId);
}
};
const updateSessionState = async (
data: Partial<EntityModels.SessionState>,
) => {
await databases.updateDocument<DatabaseModels.EstimationSession>(
DATABASE_ID,
ESTIMATION_SESSION_COLLECTION_ID,
sessionId,
{
sessionState: JSON.stringify({
...currentSessionData?.sessionState,
...data,
}),
},
);
};
const setActiveTicket = async (ticketId: string) => {
await updateSessionState({
currentTicketId: ticketId,
votes: [],
votesRevealed: false,
});
};
const setVote = async (estimate: string) => {
const userId = userData?.$id ?? ''; // TODO: Not sure if this is the user id or session
await updateSessionState({
votes: currentSessionData?.sessionState.votes
.filter((x) => x.userId !== userId)
.concat([
{
estimate: estimate,
userId: userId,
},
]),
});
};
const setRevealed = async (revealed: boolean) => {
await updateSessionState({
votesRevealed: revealed,
});
};
const createTicket = async (ticket: Omit<EstimationSessionTicket, 'id'>) => {
const newTicketsValue = currentSessionData?.tickets
.concat([
{
...ticket,
id: crypto.randomUUID(),
},
])
.map((x) => JSON.stringify(x));
await databases.updateDocument<DatabaseModels.EstimationSession>(
DATABASE_ID,
ESTIMATION_SESSION_COLLECTION_ID,
sessionId,
{
tickets: newTicketsValue,
},
);
};
return (
<EstimationContext.Provider
value={{
setSessionId: setSessionIdFunc,
setActiveTicket,
setRevealed,
setVote,
createTicket,
currentSessionData,
}}
>
{props.children}
</EstimationContext.Provider>
);
};