From acc54414a78ee8ac0f2241e777f49c5604ef1bfd Mon Sep 17 00:00:00 2001 From: Ewan Lyon Date: Thu, 25 Apr 2024 23:14:21 +1000 Subject: [PATCH] fix incentives page clearing on update --- .../admin/components/Incentives/Goal.tsx | 59 ++++------ .../admin/components/Incentives/War.tsx | 100 ++++++----------- .../admin/pages/incentives-dashboard.tsx | 105 +++++++++++++----- 3 files changed, 129 insertions(+), 135 deletions(-) diff --git a/apps/keystone/admin/components/Incentives/Goal.tsx b/apps/keystone/admin/components/Incentives/Goal.tsx index 2af8f95..f099626 100644 --- a/apps/keystone/admin/components/Incentives/Goal.tsx +++ b/apps/keystone/admin/components/Incentives/Goal.tsx @@ -1,33 +1,31 @@ import { useState } from "react"; import { Stack } from "@keystone-ui/core"; -import { - FieldContainer, - FieldLabel, - TextInput, - Checkbox, -} from "@keystone-ui/fields"; +import { FieldContainer, FieldLabel, TextInput, Checkbox } from "@keystone-ui/fields"; import { Button } from "@keystone-ui/button"; import type { Goal as GoalData } from "../../../src/schema/incentives"; import { - MutationTuple, + ApolloCache, + DefaultContext, + MutationFunctionOptions, OperationVariables, } from "@keystone-6/core/admin-ui/apollo"; import { MUTATION_UPDATE_INCENTIVE_RESULTS } from "../../pages/incentives-dashboard"; type GoalProps = { incentive: GoalData; - incentiveUpdate: MutationTuple< - MUTATION_UPDATE_INCENTIVE_RESULTS, - OperationVariables - >[0]; - refetchData: () => void; + incentiveUpdate: ( + mutationData: MutationFunctionOptions< + MUTATION_UPDATE_INCENTIVE_RESULTS, + OperationVariables, + DefaultContext, + ApolloCache + >, + ) => void; }; -export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) { - const [incentiveRawData, setIncentiveRawData] = useState( - incentive.data, - ); +export function Goal({ incentive, incentiveUpdate }: GoalProps) { + const [incentiveRawData, setIncentiveRawData] = useState(incentive.data); const [active, setActive] = useState(incentive.active); const [add, setAdd] = useState(0); @@ -35,8 +33,7 @@ export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) { function UpdateIncentive() { if (!incentive.id) return; - if (isNaN(incentiveRawData.current) || isNaN(incentiveRawData.goal)) - return; + if (isNaN(incentiveRawData.current) || isNaN(incentiveRawData.goal)) return; incentiveUpdate({ variables: { @@ -45,7 +42,6 @@ export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) { active: active, }, }); - refetchData(); } function handleAdd() { @@ -57,10 +53,7 @@ export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) { setAdd(0); } - const invalidData = - isNaN(incentiveRawData.current) || - isNaN(incentiveRawData.goal) || - !incentive.id; + const invalidData = isNaN(incentiveRawData.current) || isNaN(incentiveRawData.goal) || !incentive.id; return ( @@ -69,12 +62,8 @@ export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) {

- Needs ${incentive.data.goal - incentive.data.current} more - dollars.{" "} - {Math.round( - (incentive.data.current / incentive.data.goal) * 100, - )} - % of the way there. + Needs ${incentive.data.goal - incentive.data.current} more dollars.{" "} + {Math.round((incentive.data.current / incentive.data.goal) * 100)}% of the way there.

@@ -90,11 +79,7 @@ export function Goal({ incentive, incentiveUpdate, refetchData }: GoalProps) { width: "50%", gap: "1rem", }}> - setAdd(e.target.valueAsNumber)} - type="number" - value={add} - /> + setAdd(e.target.valueAsNumber)} type="number" value={add} />
diff --git a/apps/keystone/admin/components/Incentives/War.tsx b/apps/keystone/admin/components/Incentives/War.tsx index 0df2588..a2bd13e 100644 --- a/apps/keystone/admin/components/Incentives/War.tsx +++ b/apps/keystone/admin/components/Incentives/War.tsx @@ -1,16 +1,13 @@ import { useState } from "react"; import { Stack, Inline } from "@keystone-ui/core"; -import { - FieldContainer, - FieldLabel, - TextInput, - Checkbox, -} from "@keystone-ui/fields"; +import { FieldContainer, FieldLabel, TextInput, Checkbox } from "@keystone-ui/fields"; import { Button } from "@keystone-ui/button"; import type { War as WarData } from "../../../src/schema/incentives"; import { - MutationTuple, + ApolloCache, + DefaultContext, + MutationFunctionOptions, OperationVariables, } from "@keystone-6/core/admin-ui/apollo"; import { MUTATION_UPDATE_INCENTIVE_RESULTS } from "../../pages/incentives-dashboard"; @@ -18,31 +15,25 @@ import { MUTATION_UPDATE_INCENTIVE_RESULTS } from "../../pages/incentives-dashbo type WarProps = { incentive: WarData; - incentiveUpdate: MutationTuple< - MUTATION_UPDATE_INCENTIVE_RESULTS, - OperationVariables - >[0]; - refetchData: () => void; + incentiveUpdate: ( + mutationData: MutationFunctionOptions< + MUTATION_UPDATE_INCENTIVE_RESULTS, + OperationVariables, + DefaultContext, + ApolloCache + >, + ) => void; }; -export function War({ incentive, incentiveUpdate, refetchData }: WarProps) { - const [incentiveRawData, setIncentiveRawData] = useState( - incentive.data, - ); +export function War({ incentive, incentiveUpdate }: WarProps) { + const [incentiveRawData, setIncentiveRawData] = useState(incentive.data); const [active, setActive] = useState(incentive.active); - const [increments, setIncrements] = useState( - new Array(incentive.data.options.length).fill(0), - ); + const [increments, setIncrements] = useState(new Array(incentive.data.options.length).fill(0)); function UpdateIncentive() { if (!incentive.id) return; - if ( - incentiveRawData.options.some( - (option) => !option.name || isNaN(option.total), - ) - ) - return; + if (incentiveRawData.options.some((option) => !option.name || isNaN(option.total))) return; incentiveUpdate({ variables: { @@ -51,20 +42,14 @@ export function War({ incentive, incentiveUpdate, refetchData }: WarProps) { active: active, }, }); - refetchData(); } - const invalidData = - incentiveRawData.options.some( - (option) => !option.name || isNaN(option.total), - ) || !incentive.id; + const invalidData = incentiveRawData.options.some((option) => !option.name || isNaN(option.total)) || !incentive.id; function handleNameChange(newName: string, oldName: string) { const mutableOptions = [...incentiveRawData.options]; - const optionIndex = mutableOptions.findIndex( - (option) => option.name === oldName, - ); + const optionIndex = mutableOptions.findIndex((option) => option.name === oldName); let mutableOption = { ...mutableOptions[optionIndex] }; if (optionIndex > -1) { @@ -118,9 +103,7 @@ export function War({ incentive, incentiveUpdate, refetchData }: WarProps) { } function handleRemove(index: number) { - const mutableOptions = incentiveRawData.options.filter( - (_, i) => i !== index, - ); + const mutableOptions = incentiveRawData.options.filter((_, i) => i !== index); setIncentiveRawData({ ...incentiveRawData, @@ -138,14 +121,7 @@ export function War({ incentive, incentiveUpdate, refetchData }: WarProps) { {incentive.data.options.length > 0 ? (

- Currently{" "} - - { - [...incentive.data.options].sort( - (a, b) => b.total - a.total, - )[0].name - } - + Currently {[...incentive.data.options].sort((a, b) => b.total - a.total)[0].name}

) : (

No options submitted

@@ -172,52 +148,46 @@ export function War({ incentive, incentiveUpdate, refetchData }: WarProps) { { - handleNameChange( - e.target.value, - item.name, - ); + handleNameChange(e.target.value, item.name); }} value={item.name} + key={`input-${item.name}`} /> { - handleIncrementChange( - e.target.valueAsNumber, - i, - ); + handleIncrementChange(e.target.valueAsNumber, i); }} + key={`input-amount-${item.name}`} /> + }} + key={`total-${item.name}`}> ${item.total.toLocaleString()} {item.name === "" ? ( ) : ( - + )} ); @@ -254,11 +224,7 @@ export function War({ incentive, incentiveUpdate, refetchData }: WarProps) {

- diff --git a/apps/keystone/admin/pages/incentives-dashboard.tsx b/apps/keystone/admin/pages/incentives-dashboard.tsx index 256d915..4ba99aa 100644 --- a/apps/keystone/admin/pages/incentives-dashboard.tsx +++ b/apps/keystone/admin/pages/incentives-dashboard.tsx @@ -5,9 +5,11 @@ import { useMutation, useQuery, gql, - MutationTuple, OperationVariables, useLazyQuery, + ApolloCache, + DefaultContext, + MutationFunctionOptions, } from "@keystone-6/core/admin-ui/apollo"; import { Button } from "@keystone-ui/button"; import { Select, FieldContainer, FieldLabel } from "@keystone-ui/fields"; @@ -101,6 +103,21 @@ interface QUERY_INCENTIVES_RESULTS { }; } +interface IncentiveData { + id: string; + title: string; + notes: string; + type: string; + run: { + id: string; + game: string; + category: string; + scheduledTime: string; + }; + data: any; // use `any` if data type is unknown + active: boolean; +} + const MUTATION_UPDATE_INCENTIVE = gql` mutation ($incentive: ID, $active: Boolean, $data: JSON) { updateIncentive(where: { id: $incentive }, data: { data: $data, active: $active }) { @@ -125,28 +142,20 @@ const incentiveTypes = [ function renderIncentive( // @ts-ignore incentive: QUERY_INCENTIVES_RESULTS["event"]["donationIncentives"][0], - updateIncentiveMutation: MutationTuple[0], - refetchData: () => void, + updateIncentiveMutation: ( + mutationData: MutationFunctionOptions< + MUTATION_UPDATE_INCENTIVE_RESULTS, + OperationVariables, + DefaultContext, + ApolloCache + >, + ) => void, ) { switch (incentive?.type) { case "war": - return ( - - ); + return ; case "goal": - return ( - - ); + return ; case undefined: return <>; default: @@ -163,11 +172,16 @@ type SelectOption = { export default function RunsManager() { const [selectedEvent, setSelectedEvent] = useState(getEventInURLQuery()); const [selectedIncentiveIndex, setSelectedIncentiveIndex] = useState(0); + const [sortedIncentives, setSortedIncentiveData] = useState([]); + const [incentiveData, setIncentiveData] = useState(undefined); + const [actualEventData, setActualEventData] = useState(undefined); const { addToast } = useToasts(); const eventsList = useQuery(QUERY_EVENTS); - const [refetchEventData, { data: eventData }] = useLazyQuery(QUERY_INCENTIVES); + const [refetchEventData, { data: eventData }] = useLazyQuery(QUERY_INCENTIVES, { + fetchPolicy: "no-cache", + }); const [updateIncentiveMutation, updateIncentiveMutationData] = useMutation(MUTATION_UPDATE_INCENTIVE); @@ -177,11 +191,22 @@ export default function RunsManager() { label: event.shortname, })); - const sortedIncentives = eventData?.event?.donationIncentives.map((a) => ({ ...a })) ?? []; - sortedIncentives.sort( - (a, b) => new Date(a.run?.scheduledTime ?? 0).getTime() - new Date(b.run?.scheduledTime ?? 0).getTime(), - ); - const incentiveData = sortedIncentives[selectedIncentiveIndex]; + useEffect(() => { + setActualEventData(eventData); + }, [eventData]); + + useEffect(() => { + const mutableSortedIncentives = actualEventData?.event?.donationIncentives.map((a) => ({ ...a })) ?? []; + mutableSortedIncentives.sort( + (a, b) => new Date(a.run?.scheduledTime ?? 0).getTime() - new Date(b.run?.scheduledTime ?? 0).getTime(), + ); + + setSortedIncentiveData(mutableSortedIncentives); + }, [actualEventData]); + + useEffect(() => { + setIncentiveData(sortedIncentives[selectedIncentiveIndex]); + }, [sortedIncentives, selectedIncentiveIndex]); function handleEventSelection(option: { label: string; value: string } | null) { const urlParams = new URLSearchParams(window.location.search); @@ -216,7 +241,7 @@ export default function RunsManager() { } useEffect(() => { - if (selectedEvent?.value) refetchEventData({ variables: { event: selectedEvent.value } }); + refetchCurrentEvent(); }, [selectedEvent]); // Update Incentive Feedback @@ -239,6 +264,28 @@ export default function RunsManager() { } }, [updateIncentiveMutationData.data, updateIncentiveMutationData.error]); + function refetchCurrentEvent() { + if (selectedEvent?.value) { + refetchEventData({ variables: { event: selectedEvent.value } }).then((data) => { + setActualEventData(data.data); + console.log("New data", data.data); + }); + } + } + + function mutateDataAndThenRefetch( + mutationData: MutationFunctionOptions< + MUTATION_UPDATE_INCENTIVE_RESULTS, + OperationVariables, + DefaultContext, + ApolloCache + >, + ) { + updateIncentiveMutation(mutationData).then(() => { + refetchCurrentEvent(); + }); + } + return (
Add incentive - + - {eventData?.event && ( + {actualEventData?.event && ( <>
Notes {incentiveData?.notes}

- {renderIncentive(incentiveData, updateIncentiveMutation, refetchEventData)} + {renderIncentive(incentiveData, mutateDataAndThenRefetch)}