-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(wallet/frontend): separate card state from side view (#1555)
* Add initial cards api * Add card service mock * Format * Separate card state from view; use context * Format * Update card actions; layout shift fixed * Center card on mobile * Fix overflowing for text * Consistent naming across components
- Loading branch information
1 parent
f914cce
commit 1620a87
Showing
4 changed files
with
208 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 127 additions & 43 deletions
170
packages/wallet/frontend/src/components/userCards/UserCardActions.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,148 @@ | ||
import { Button } from '@/ui/Button' | ||
import { Eye, EyeCross, Snow, Trash } from '../icons/CardButtons' | ||
import { Dispatch, SetStateAction, useState } from 'react' | ||
import type { CardType } from './UserCard' | ||
import { useCardContext } from './UserCardContext' | ||
import { cardServiceMock } from '@/lib/api/card' | ||
import { useRouter } from 'next/router' | ||
import { Cog } from '../icons/Cog' | ||
|
||
interface CardActionsProps { | ||
fn: Dispatch<SetStateAction<CardType>> | ||
export const FrozenCardActions = () => { | ||
const router = useRouter() | ||
|
||
return ( | ||
<> | ||
<div className="flex flex-col gap-y-4"> | ||
<Button | ||
intent="primary" | ||
aria-label="unfreeze" | ||
onClick={async () => { | ||
// Maybe use toats for showcasing the result of the api calls, | ||
// specifically for card actions? | ||
// We will probably have a lot more dialogs for card settings | ||
// and using dialogs again for showing the response might be a bit | ||
// cumbersome. | ||
const response = await cardServiceMock.unfreeze() | ||
|
||
if (!response.success) { | ||
console.error('[TODO] UPDATE ME - error while unfreezing card') | ||
} | ||
|
||
if (response.success) { | ||
router.replace(router.asPath) | ||
} | ||
}} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
<Snow className="size-6" /> | ||
</div> | ||
</Button> | ||
<p className="text-center -tracking-wide text-sm">Unfreeze</p> | ||
</div> | ||
<div className="col-span-2 flex flex-col gap-y-4"> | ||
<Button | ||
intent="danger" | ||
aria-label="terminate card" | ||
onClick={async () => { | ||
// Maybe use toats for showcasing the result of the api calls, | ||
// specifically for card actions? | ||
// We will probably have a lot more dialogs for card settings | ||
// and using dialogs again for showing the response might be a bit | ||
// cumbersome. | ||
const response = await cardServiceMock.terminate() | ||
|
||
if (!response.success) { | ||
console.error('[TODO] UPDATE ME - error while terminating card') | ||
} | ||
|
||
if (response.success) { | ||
router.replace(router.asPath) | ||
} | ||
}} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
<Trash className="size-6" /> | ||
</div> | ||
</Button> | ||
<p className="text-center -tracking-wide text-sm">Terminate</p> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
// TODO: Better naming for the function | ||
export const CardActions = ({ fn }: CardActionsProps) => { | ||
const [isDetailed, setIsDetailed] = useState(false) | ||
const [isFrozen, setIsFrozen] = useState(false) | ||
const DefaultCardActions = () => { | ||
const router = useRouter() | ||
const { showDetails, setShowDetails } = useCardContext() | ||
|
||
// ToDO revisit button layout shift, when clicking on butttons | ||
return ( | ||
<div className="flex gap-x-3 justify-center items-center"> | ||
<Button | ||
intent={isFrozen ? 'primary' : 'secondary'} | ||
aria-label="freeze" | ||
onClick={() => { | ||
setIsFrozen(!isFrozen) | ||
isFrozen ? fn('normal') : fn('frozen') | ||
}} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
<Snow /> | ||
{isFrozen ? 'Unfreeze' : 'Freeze'} | ||
</div> | ||
</Button> | ||
{!isFrozen ? ( | ||
<> | ||
<div className="flex flex-col gap-y-4"> | ||
<Button | ||
aria-label="details" | ||
intent={isDetailed ? 'primary' : 'secondary'} | ||
onClick={() => { | ||
setIsDetailed(!isDetailed) | ||
isDetailed ? fn('normal') : fn('details') | ||
intent="secondary" | ||
aria-label="freeze" | ||
onClick={async () => { | ||
// Maybe use toats for showcasing the result of the api calls, | ||
// specifically for card actions? | ||
// We will probably have a lot more dialogs for card settings | ||
// and using dialogs again for showing the response might be a bit | ||
// cumbersome. | ||
const response = await cardServiceMock.freeze() | ||
|
||
if (!response.success) { | ||
console.error('[TODO] UPDATE ME - error while freezing card') | ||
} | ||
|
||
if (response.success) { | ||
router.replace(router.asPath) | ||
} | ||
}} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
{isDetailed ? ( | ||
<> | ||
<EyeCross /> | ||
Hide Details | ||
</> | ||
<Snow className="size-6" /> | ||
</div> | ||
</Button> | ||
<p className="text-center -tracking-wide text-sm">Freeze</p> | ||
</div> | ||
<div className="flex flex-col gap-y-4"> | ||
<Button | ||
intent="secondary" | ||
aria-label={showDetails ? 'hide details' : 'show details'} | ||
onClick={() => setShowDetails((prev) => !prev)} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
{showDetails ? ( | ||
<EyeCross className="size-6" /> | ||
) : ( | ||
<> | ||
<Eye /> | ||
Details | ||
</> | ||
<Eye className="size-6" /> | ||
)} | ||
</div> | ||
</Button> | ||
) : ( | ||
<Button intent="danger" aria-label="terminate"> | ||
<p className="text-center -tracking-wide text-sm"> | ||
{showDetails ? 'Hide Details' : 'Details'} | ||
</p> | ||
</div> | ||
<div className="flex flex-col gap-y-4"> | ||
<Button | ||
intent="secondary" | ||
aria-label="settings" | ||
onClick={() => { | ||
// TODO: TBD | ||
}} | ||
> | ||
<div className="flex gap-2 justify-center items-center"> | ||
<Trash /> | ||
Terminate | ||
<Cog className="size-6" /> | ||
</div> | ||
</Button> | ||
)} | ||
<p className="text-center -tracking-wide text-sm">Settings</p> | ||
</div> | ||
</> | ||
) | ||
} | ||
|
||
export const UserCardActions = () => { | ||
const { card } = useCardContext() | ||
|
||
return ( | ||
<div className="grid grid-cols-3 gap-x-3"> | ||
{card.isFrozen ? <FrozenCardActions /> : <DefaultCardActions />} | ||
</div> | ||
) | ||
} |
27 changes: 27 additions & 0 deletions
27
packages/wallet/frontend/src/components/userCards/UserCardContext.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { IUserCard } from '@/lib/api/card' | ||
import { | ||
createContext, | ||
useContext, | ||
type Dispatch, | ||
type SetStateAction | ||
} from 'react' | ||
|
||
interface UserCardContextValue { | ||
showDetails: boolean | ||
setShowDetails: Dispatch<SetStateAction<boolean>> | ||
card: IUserCard | ||
} | ||
|
||
export const UserCardContext = createContext({} as UserCardContextValue) | ||
|
||
export const useCardContext = () => { | ||
const cardContext = useContext(UserCardContext) | ||
|
||
if (!cardContext) { | ||
throw new Error( | ||
'"useCardContext" is used outside the UserCardContext provider.' | ||
) | ||
} | ||
|
||
return cardContext | ||
} |
Oops, something went wrong.