From fc15332d6a1cf1362c4db72909f01c9aec07a6c7 Mon Sep 17 00:00:00 2001 From: Xenepix Date: Tue, 13 Feb 2024 19:04:25 +0100 Subject: [PATCH 1/3] refactor(MoneyActionButtons): externalize destructive toast event for operations with real money --- .../moneyActions/spaceMoneyActionButtons.tsx | 65 +----------------- .../unavailableMoneyActionButton.tsx | 68 +++++++++++++++++++ 2 files changed, 71 insertions(+), 62 deletions(-) create mode 100644 desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx diff --git a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx index 36a1c44e..c9fd04bf 100644 --- a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx +++ b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx @@ -4,6 +4,7 @@ import { spaceInvest, spacePossibleInvestments } from '@/api/spaces/spaces' +import UnavailableMoneyActionButton from '@/components/custom/moneyActions/unavailableMoneyActionButton' import CustomForm from '@/components/custom/selectedObject/inputs' import { Button } from '@/components/ui/button' import { @@ -21,10 +22,7 @@ import { TooltipTrigger } from '@/components/ui/tooltip' import { useToast } from '@/components/ui/use-toast' -import { - ArrowDownOnSquareIcon, - ArrowUpOnSquareIcon -} from '@heroicons/react/24/outline' +import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline' import { useSearchParams } from 'next/navigation' import { useEffect, useState } from 'react' import * as z from 'zod' @@ -209,64 +207,7 @@ export default function SpaceMoneyActionButtons({ )} - {!space.testing && ( -
- - - -
- -
-
- -

Deposit

-
-
-
- - - -
- -
-
- -

Withdraw

-
-
-
-
- )} + {!space.testing && } ) } diff --git a/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx b/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx new file mode 100644 index 00000000..5ca5c3c7 --- /dev/null +++ b/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx @@ -0,0 +1,68 @@ +import { Button } from '@/components/ui/button' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '@/components/ui/tooltip' +import { useToast } from '@/components/ui/use-toast' +import { + ArrowDownOnSquareIcon, + ArrowUpOnSquareIcon +} from '@heroicons/react/24/outline' + +export default function UnavailableMoneyActionButton({}: {}): JSX.Element { + const { toast } = useToast() + return ( +
+ + + +
+ +
+
+ +

Deposit

+
+
+
+ + + +
+ +
+
+ +

Withdraw

+
+
+
+
+ ) +} From 091bee37f38b9c3a0d840eb553941431b30f213a Mon Sep 17 00:00:00 2001 From: Xenepix Date: Tue, 13 Feb 2024 21:18:06 +0100 Subject: [PATCH 2/3] work on MoneyActionButtons --- desktop-app/renderer/api/spaces/spaces.ts | 14 +- .../moneyActions/moneyActionButtons.tsx | 245 ++++++++++++++++++ .../moneyActions/spaceMoneyActionButtons.tsx | 159 +----------- .../unavailableMoneyActionButton.tsx | 1 + 4 files changed, 257 insertions(+), 162 deletions(-) create mode 100644 desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx diff --git a/desktop-app/renderer/api/spaces/spaces.ts b/desktop-app/renderer/api/spaces/spaces.ts index 6f74b643..8c23fcc5 100644 --- a/desktop-app/renderer/api/spaces/spaces.ts +++ b/desktop-app/renderer/api/spaces/spaces.ts @@ -76,28 +76,28 @@ export async function createSpace( return response as AxiosResponse } -// Investments related -export interface Investment { +// Operation related +export interface Operation { ticker: string amount: number } export async function spacePossibleInvestments( searchParams: ReturnType, space: RetrievedNapseSpace -): Promise> { +): Promise> { const response = await request( searchParams, 'GET', `/api/space/${space.uuid}/invest/` ) - return response as AxiosResponse + return response as AxiosResponse } export async function spaceInvest( searchParams: ReturnType, space: RetrievedNapseSpace, - investment: Investment -): Promise> { + investment: Operation +): Promise> { const formated_investment = convertInterfaceToSnakeCaseDict(investment) console.log('investment', investment) console.log('formated_investment', formated_investment) @@ -107,5 +107,5 @@ export async function spaceInvest( `/api/space/${space.uuid}/invest/`, formated_investment ) - return response as AxiosResponse + return response as AxiosResponse } diff --git a/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx b/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx new file mode 100644 index 00000000..02a9368b --- /dev/null +++ b/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx @@ -0,0 +1,245 @@ +import { Operation } from '@/api/spaces/spaces' +import CustomForm from '@/components/custom/selectedObject/inputs' +import { Button } from '@/components/ui/button' +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger +} from '@/components/ui/dialog' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '@/components/ui/tooltip' +import { useToast } from '@/components/ui/use-toast' +import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline' +import { AxiosResponse } from 'axios' +import { ReadonlyURLSearchParams, useSearchParams } from 'next/navigation' +import { useEffect, useState } from 'react' +import * as z from 'zod' + +const OperationSchema = z.object({ + ticker: z + .string() + .min(2, { message: 'You have to give an existing currency.' }) + .max(8, { message: 'You have to give an existing currency.' }), + amount: z.number() +}) + +interface ObjectWithName extends Object { + name: string +} +interface getProps { + ( + searchParams: ReadonlyURLSearchParams, + object: T + ): Promise> +} + +interface postProps { + ( + searchParams: ReadonlyURLSearchParams, + object: T, + operation: Operation + ): Promise> +} + +export function InvestMoneyActionButton({ + object, + getPossibleInvestmentsCallback, + postInvestmentCallback +}: { + object: T + getPossibleInvestmentsCallback: getProps + postInvestmentCallback: postProps +}): JSX.Element { + const { toast } = useToast() + const searchParams = useSearchParams() + const [possibleInvestments, setPossibleInvestments] = useState( + [] + ) + const [selectedTicker, setSelectedTicker] = useState('') + + useEffect(() => { + const fetchPossibleInvestments = async () => { + try { + const response = await getPossibleInvestmentsCallback( + searchParams, + object + ) + setPossibleInvestments(response.data) + } catch (error) { + console.error(error) + setPossibleInvestments([]) + } + } + if (searchParams.get('server')) { + fetchPossibleInvestments() + } + }, [searchParams, object, getPossibleInvestmentsCallback]) + + const PossibleInvestmentTickerSelection = possibleInvestments.reduce( + (obj, item) => { + obj[item.ticker] = item.ticker + return obj + }, + {} as { [key: string]: string } + ) + + return ( + { + setSelectedTicker(' ') + }} + > + + + +
+ + + +
+
+ +

Deposit

+
+
+
+ + + Invest on {object.name} + + Allocate money of your exchange account to the space. + + + + + inputs={[ + { + label: 'Ticker', + key: 'ticker', + type: 'select', + possibilities: PossibleInvestmentTickerSelection, + zod: z.string(), + placeholder: 'Select a ticker', + setter: setSelectedTicker + }, + { + label: 'Amount', + key: 'amount', + type: 'input', + zod: z.number(), + default: 0, + placeholder: 0 + } + ]} + onSubmit={async (values) => { + const newInvestment: Operation = { + ticker: selectedTicker, + amount: values.amount + } + try { + const response = await postInvestmentCallback( + searchParams, + object, + newInvestment + ) + console.log('response::', response) + toast({ + title: 'Investment', + description: 'You have invested money !' + }) + } catch (error) { + console.error(error) + toast({ + title: 'Investment', + description: 'You cannot invest money yet.', + variant: 'destructive' + }) + } + }} + buttonDescription="Done" + /> + + + {possibleInvestments.find((inv) => inv.ticker === selectedTicker) + ?.amount + ? `max: ${possibleInvestments.find( + (inv) => inv.ticker === selectedTicker + )?.amount} ${selectedTicker}` + : ''} + + +
+ ) +} + +export function WithdrawMoneyActionButton({ + object, + getPossibleWithdrawCallback, + postWithdrawCallback +}: { + object: T + getPossibleWithdrawCallback: getProps + postWithdrawCallback: postProps +}): JSX.Element { + return ( + + + + +
+ + + +
+
+ +

Deposit

+
+
+
+ + + Withdraw from {object.name} + + You deallocate money from the space. He won't be able to manage + it + + + +
+ ) +} + +export default function OperationMoneyActionButton< + T extends ObjectWithName +>({} // object, +// getPossibleInvestmentsCallback, +// postInvestmentCallback, +// getPossibleWithdrawCallback, +// postWithdrawCallback +: { + // object: T + // getPossibleInvestmentsCallback: getProps + // postInvestmentCallback: postProps + // getPossibleWithdrawCallback: getProps + // postWithdrawCallback: postProps +}): JSX.Element { + return <> +} diff --git a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx index c9fd04bf..356bbb06 100644 --- a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx +++ b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx @@ -1,28 +1,11 @@ import { - Investment, + Operation, RetrievedNapseSpace, - spaceInvest, spacePossibleInvestments } from '@/api/spaces/spaces' +import OperationMoneyActionButton from '@/components/custom/moneyActions/moneyActionButtons' import UnavailableMoneyActionButton from '@/components/custom/moneyActions/unavailableMoneyActionButton' -import CustomForm from '@/components/custom/selectedObject/inputs' -import { Button } from '@/components/ui/button' -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, - DialogTrigger -} from '@/components/ui/dialog' -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger -} from '@/components/ui/tooltip' import { useToast } from '@/components/ui/use-toast' -import { ArrowDownOnSquareIcon } from '@heroicons/react/24/outline' import { useSearchParams } from 'next/navigation' import { useEffect, useState } from 'react' import * as z from 'zod' @@ -42,7 +25,7 @@ export default function SpaceMoneyActionButtons({ }): JSX.Element { const { toast } = useToast() const searchParams = useSearchParams() - const [possibleInvestments, setPossibleInvestments] = useState( + const [possibleInvestments, setPossibleInvestments] = useState( [] ) const [selectedTicker, setSelectedTicker] = useState('') @@ -72,141 +55,7 @@ export default function SpaceMoneyActionButtons({ return ( <> - {space.testing && ( -
- { - setSelectedTicker(' ') - }} - > - - - -
- - - -
-
- -

Deposit

-
-
-
- - - Invest on {space.name} - - Allocate money of your exchange account to the space. - - - - - inputs={[ - { - label: 'Ticker', - key: 'ticker', - type: 'select', - possibilities: PossibleInvestmentTickerSelection, - zod: z.string(), - placeholder: 'Select a ticker', - setter: setSelectedTicker - }, - { - label: 'Amount', - key: 'amount', - type: 'input', - zod: z.number(), - // value: selectedAmount, - // setter: setSelectedAmount, - // placeholder: possibleInvestments.find( - // (inv) => inv.ticker === selectedTicker - // ) - // ? `max: ${possibleInvestments.find( - // (inv) => inv.ticker === selectedTicker - // )?.amount} ${selectedTicker}` - // : ' ' - default: 0, - placeholder: 0 - } - ]} - onSubmit={async (values) => { - const newInvestment: Investment = { - ticker: selectedTicker, - amount: values.amount - } - try { - const response = await spaceInvest( - searchParams, - space, - newInvestment - ) - console.log('response::', response) - toast({ - title: 'Investment', - description: 'You have invested money !' - }) - } catch (error) { - console.error(error) - toast({ - title: 'Investment', - description: 'You cannot invest money yet.', - variant: 'destructive' - }) - } - }} - buttonDescription="Done" - /> - - - {possibleInvestments.find( - (inv) => inv.ticker === selectedTicker - )?.amount - ? `max: ${possibleInvestments.find( - (inv) => inv.ticker === selectedTicker - )?.amount} ${selectedTicker}` - : ''} - - -
- - - - - -
- - - -
-
- -

Deposit

-
-
-
- - - Withdraw from {space.name} - - You deallocate money from the space. He won't be able to - manage it - - - -
-
- )} + {space.testing && } {!space.testing && } ) diff --git a/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx b/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx index 5ca5c3c7..41047bae 100644 --- a/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx +++ b/desktop-app/renderer/components/custom/moneyActions/unavailableMoneyActionButton.tsx @@ -39,6 +39,7 @@ export default function UnavailableMoneyActionButton({}: {}): JSX.Element { + From a5b1550f8bf915b053dc5b3b3c48dbaa84d814d0 Mon Sep 17 00:00:00 2001 From: Xenepix Date: Wed, 14 Feb 2024 22:06:32 +0100 Subject: [PATCH 3/3] finish abstraction for Money action Buttons & add Operation Context for auto reload --- desktop-app/renderer/api/spaces/spaces.ts | 36 +++++++-- .../moneyActions/moneyActionButtons.tsx | 81 ++++++++++++------- .../custom/moneyActions/operationContext.tsx | 23 ++++++ .../moneyActions/spaceMoneyActionButtons.tsx | 49 +++-------- .../renderer/pages/spaces/[slug]/index.tsx | 9 ++- 5 files changed, 125 insertions(+), 73 deletions(-) create mode 100644 desktop-app/renderer/components/custom/moneyActions/operationContext.tsx diff --git a/desktop-app/renderer/api/spaces/spaces.ts b/desktop-app/renderer/api/spaces/spaces.ts index 8c23fcc5..819879b9 100644 --- a/desktop-app/renderer/api/spaces/spaces.ts +++ b/desktop-app/renderer/api/spaces/spaces.ts @@ -76,7 +76,7 @@ export async function createSpace( return response as AxiosResponse } -// Operation related +// Invest related export interface Operation { ticker: string amount: number @@ -98,14 +98,40 @@ export async function spaceInvest( space: RetrievedNapseSpace, investment: Operation ): Promise> { - const formated_investment = convertInterfaceToSnakeCaseDict(investment) - console.log('investment', investment) - console.log('formated_investment', formated_investment) + const formated_operation = convertInterfaceToSnakeCaseDict(investment) const response = await request( searchParams, 'POST', `/api/space/${space.uuid}/invest/`, - formated_investment + formated_operation + ) + return response as AxiosResponse +} + +// Withdraw related +export async function spacePossibleWithdraws( + searchParams: ReturnType, + space: RetrievedNapseSpace +): Promise> { + const response = await request( + searchParams, + 'GET', + `/api/space/${space.uuid}/withdraw/` + ) + return response as AxiosResponse +} + +export async function spaceWithdraw( + searchParams: ReturnType, + space: RetrievedNapseSpace, + investment: Operation +): Promise> { + const formated_operation = convertInterfaceToSnakeCaseDict(investment) + const response = await request( + searchParams, + 'POST', + `/api/space/${space.uuid}/withdraw/`, + formated_operation ) return response as AxiosResponse } diff --git a/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx b/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx index 02a9368b..c5e50139 100644 --- a/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx +++ b/desktop-app/renderer/components/custom/moneyActions/moneyActionButtons.tsx @@ -9,6 +9,8 @@ import { DialogTitle, DialogTrigger } from '@/components/ui/dialog' +import { DialogClose } from '@radix-ui/react-dialog' + import { Tooltip, TooltipContent, @@ -21,6 +23,7 @@ import { AxiosResponse } from 'axios' import { ReadonlyURLSearchParams, useSearchParams } from 'next/navigation' import { useEffect, useState } from 'react' import * as z from 'zod' +import { useOperationContext } from './operationContext' const OperationSchema = z.object({ ticker: z @@ -33,20 +36,16 @@ const OperationSchema = z.object({ interface ObjectWithName extends Object { name: string } -interface getProps { - ( - searchParams: ReadonlyURLSearchParams, - object: T - ): Promise> -} -interface postProps { - ( - searchParams: ReadonlyURLSearchParams, - object: T, - operation: Operation - ): Promise> -} +type getCallbackType = ( + searchParams: ReadonlyURLSearchParams, + object: T +) => Promise> +type postCallbackType = ( + searchParams: ReadonlyURLSearchParams, + object: T, + investment: Operation +) => Promise> export function InvestMoneyActionButton({ object, @@ -54,8 +53,8 @@ export function InvestMoneyActionButton({ postInvestmentCallback }: { object: T - getPossibleInvestmentsCallback: getProps - postInvestmentCallback: postProps + getPossibleInvestmentsCallback: getCallbackType + postInvestmentCallback: postCallbackType }): JSX.Element { const { toast } = useToast() const searchParams = useSearchParams() @@ -63,6 +62,7 @@ export function InvestMoneyActionButton({ [] ) const [selectedTicker, setSelectedTicker] = useState('') + const { setTriggerRefresh } = useOperationContext() useEffect(() => { const fetchPossibleInvestments = async () => { @@ -155,6 +155,11 @@ export function InvestMoneyActionButton({ newInvestment ) console.log('response::', response) + if (response.status === 200) { + // Trigger space refresh + setTriggerRefresh((prev) => !prev) + } + toast({ title: 'Investment', description: 'You have invested money !' @@ -167,6 +172,7 @@ export function InvestMoneyActionButton({ variant: 'destructive' }) } + document.getElementById('close-invest-button')?.click() }} buttonDescription="Done" /> @@ -180,6 +186,7 @@ export function InvestMoneyActionButton({ : ''} + ) } @@ -190,8 +197,8 @@ export function WithdrawMoneyActionButton({ postWithdrawCallback }: { object: T - getPossibleWithdrawCallback: getProps - postWithdrawCallback: postProps + getPossibleWithdrawCallback: getCallbackType + postWithdrawCallback: postCallbackType }): JSX.Element { return ( @@ -227,19 +234,31 @@ export function WithdrawMoneyActionButton({ ) } -export default function OperationMoneyActionButton< - T extends ObjectWithName ->({} // object, -// getPossibleInvestmentsCallback, -// postInvestmentCallback, -// getPossibleWithdrawCallback, -// postWithdrawCallback -: { - // object: T - // getPossibleInvestmentsCallback: getProps - // postInvestmentCallback: postProps - // getPossibleWithdrawCallback: getProps - // postWithdrawCallback: postProps +export default function OperationMoneyActionButton({ + object, + getPossibleInvestmentsCallback, + postInvestmentCallback, + getPossibleWithdrawCallback, + postWithdrawCallback +}: { + object: T + getPossibleInvestmentsCallback: getCallbackType + postInvestmentCallback: postCallbackType + getPossibleWithdrawCallback: getCallbackType + postWithdrawCallback: postCallbackType }): JSX.Element { - return <> + return ( +
+ + +
+ ) } diff --git a/desktop-app/renderer/components/custom/moneyActions/operationContext.tsx b/desktop-app/renderer/components/custom/moneyActions/operationContext.tsx new file mode 100644 index 00000000..236368e2 --- /dev/null +++ b/desktop-app/renderer/components/custom/moneyActions/operationContext.tsx @@ -0,0 +1,23 @@ +import { ReactNode, createContext, useContext, useState } from 'react' + +const OperationContext = createContext<{ + triggerRefresh: boolean + setTriggerRefresh: React.Dispatch> +}>({ + triggerRefresh: false, + setTriggerRefresh: () => {} +}) + +export const useOperationContext = () => useContext(OperationContext) + +export const OperationProvider: React.FC<{ children: ReactNode }> = ({ + children +}) => { + const [triggerRefresh, setTriggerRefresh] = useState(false) + + return ( + + {children} + + ) +} diff --git a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx index 356bbb06..2c618852 100644 --- a/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx +++ b/desktop-app/renderer/components/custom/moneyActions/spaceMoneyActionButtons.tsx @@ -1,13 +1,12 @@ import { - Operation, RetrievedNapseSpace, - spacePossibleInvestments + spaceInvest, + spacePossibleInvestments, + spacePossibleWithdraws, + spaceWithdraw } from '@/api/spaces/spaces' import OperationMoneyActionButton from '@/components/custom/moneyActions/moneyActionButtons' import UnavailableMoneyActionButton from '@/components/custom/moneyActions/unavailableMoneyActionButton' -import { useToast } from '@/components/ui/use-toast' -import { useSearchParams } from 'next/navigation' -import { useEffect, useState } from 'react' import * as z from 'zod' const InvestmentSchema = z.object({ @@ -23,39 +22,17 @@ export default function SpaceMoneyActionButtons({ }: { space: RetrievedNapseSpace }): JSX.Element { - const { toast } = useToast() - const searchParams = useSearchParams() - const [possibleInvestments, setPossibleInvestments] = useState( - [] - ) - const [selectedTicker, setSelectedTicker] = useState('') - - useEffect(() => { - const fetchPossibleInvestments = async () => { - try { - const response = await spacePossibleInvestments(searchParams, space) - setPossibleInvestments(response.data) - } catch (error) { - console.error(error) - setPossibleInvestments([]) - } - } - if (searchParams.get('server')) { - fetchPossibleInvestments() - } - }, [searchParams, space]) - - const PossibleInvestmentTickerSelection = possibleInvestments.reduce( - (obj, item) => { - obj[item.ticker] = item.ticker - return obj - }, - {} as { [key: string]: string } - ) - return ( <> - {space.testing && } + {space.testing && ( + + object={space} + getPossibleInvestmentsCallback={spacePossibleInvestments} + postInvestmentCallback={spaceInvest} + getPossibleWithdrawCallback={spacePossibleWithdraws} + postWithdrawCallback={spaceWithdraw} + /> + )} {!space.testing && } ) diff --git a/desktop-app/renderer/pages/spaces/[slug]/index.tsx b/desktop-app/renderer/pages/spaces/[slug]/index.tsx index e93910dd..ccf9342e 100644 --- a/desktop-app/renderer/pages/spaces/[slug]/index.tsx +++ b/desktop-app/renderer/pages/spaces/[slug]/index.tsx @@ -1,6 +1,7 @@ import { Fleet, listFleet } from '@/api/fleets/fleets' import { Key, getCurrentKey } from '@/api/key/key' import { RetrievedNapseSpace, retrieveSpace } from '@/api/spaces/spaces' +import { useOperationContext } from '@/components/custom/moneyActions/operationContext' import InfoPanelCard from '@/components/custom/panel/infoPanelCard' import ValuePanelCard from '@/components/custom/panel/valuePanelCard' import ContextHeader from '@/components/layout/contextHeader' @@ -58,6 +59,7 @@ export default function Space(): JSX.Element { const [space, setSpace] = useState() const [fleets, setFleets] = useState([]) + const { triggerRefresh, setTriggerRefresh } = useOperationContext() useEffect(() => { async function fetchSpace() { @@ -87,7 +89,12 @@ export default function Space(): JSX.Element { fetchFleets() fetchCurrentKey({ setCurrentKey, searchParams }) } - }, [spaceID, searchParams, router]) + + // Operation trigger + if (triggerRefresh) { + fetchSpace() + } + }, [spaceID, searchParams, router, triggerRefresh]) if (!space) { // TODO: setup a squeleton or a loader