Skip to content

Commit

Permalink
Fix cancellation and improve frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
razzeee committed Nov 14, 2024
1 parent c2968ad commit e2832d9
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 24 deletions.
2 changes: 1 addition & 1 deletion backend/app/vending/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ def create_tokens(

class TokenCancellation(BaseModel):
token: str
status: str
status: Literal["invalid", "cancelled", "error"]


@router.post("app/{app_id}/tokens/cancel", tags=["vending"])
Expand Down
1 change: 1 addition & 0 deletions frontend/src/codegen/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ export * from "./storefrontInfoVerification"
export * from "./stripeKeys"
export * from "./submitReviewModerationRequestsIdReviewPost200"
export * from "./tokenCancellation"
export * from "./tokenCancellationStatus"
export * from "./tokenList"
export * from "./tokenModel"
export * from "./tokenModelState"
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/codegen/model/tokenCancellation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* Flathub API
* OpenAPI spec version: 0.1.0
*/
import type { TokenCancellationStatus } from "./tokenCancellationStatus"

export interface TokenCancellation {
status: string
status: TokenCancellationStatus
token: string
}
16 changes: 16 additions & 0 deletions frontend/src/codegen/model/tokenCancellationStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Generated by orval 🍺
* Do not edit manually.
* Flathub API
* OpenAPI spec version: 0.1.0
*/

export type TokenCancellationStatus =
(typeof TokenCancellationStatus)[keyof typeof TokenCancellationStatus]

// eslint-disable-next-line @typescript-eslint/no-redeclare
export const TokenCancellationStatus = {
invalid: "invalid",
cancelled: "cancelled",
error: "error",
} as const
24 changes: 22 additions & 2 deletions frontend/src/codegen/users/users.msw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const getUsersUsersGetResponseMock = (
]),
default_account: faker.helpers.arrayElement([
{
avatar_url: faker.word.sample(),
avatar_url: faker.helpers.arrayElement([faker.word.sample(), null]),
display_name: faker.helpers.arrayElement([faker.word.sample(), null]),
email: faker.helpers.arrayElement([faker.word.sample(), null]),
github_userid: faker.number.int({ min: undefined, max: undefined }),
Expand All @@ -51,6 +51,16 @@ export const getUsersUsersGetResponseMock = (
]),
deleted: faker.datatype.boolean(),
display_name: faker.helpers.arrayElement([faker.word.sample(), null]),
github_repos: faker.helpers.arrayElement([
Array.from(
{ length: faker.number.int({ min: 1, max: 10 }) },
(_, i) => i + 1,
).map(() => ({
id: faker.number.int({ min: undefined, max: undefined }),
reponame: faker.word.sample(),
})),
null,
]),
id: faker.number.int({ min: undefined, max: undefined }),
owned_apps: faker.helpers.arrayElement([
Array.from(
Expand Down Expand Up @@ -91,7 +101,7 @@ export const getUserUsersUserIdGetResponseMock = (
// @ts-expect-error
default_account: faker.helpers.arrayElement([
{
avatar_url: faker.word.sample(),
avatar_url: faker.helpers.arrayElement([faker.word.sample(), null]),
display_name: faker.helpers.arrayElement([faker.word.sample(), null]),
email: faker.helpers.arrayElement([faker.word.sample(), null]),
github_userid: faker.number.int({ min: undefined, max: undefined }),
Expand All @@ -113,6 +123,16 @@ export const getUserUsersUserIdGetResponseMock = (
]),
deleted: faker.datatype.boolean(),
display_name: faker.helpers.arrayElement([faker.word.sample(), null]),
github_repos: faker.helpers.arrayElement([
Array.from(
{ length: faker.number.int({ min: 1, max: 10 }) },
(_, i) => i + 1,
).map(() => ({
id: faker.number.int({ min: undefined, max: undefined }),
reponame: faker.word.sample(),
})),
null,
]),
id: faker.number.int({ min: undefined, max: undefined }),
owned_apps: faker.helpers.arrayElement([
Array.from(
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/codegen/vending/vending.msw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,14 @@ export const getCancelTokensVendingappAppIdTokensCancelPostResponseMock =
Array.from(
{ length: faker.number.int({ min: 1, max: 10 }) },
(_, i) => i + 1,
).map(() => ({ status: faker.word.sample(), token: faker.word.sample() }))
).map(() => ({
status: faker.helpers.arrayElement([
"invalid",
"cancelled",
"error",
] as const),
token: faker.word.sample(),
}))

export const getRedeemTokenVendingappAppIdTokensRedeemTokenPostResponseMock = (
overrideResponse: Partial<RedemptionResult> = {},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useTranslation } from "next-i18next"
import { FunctionComponent } from "react"
import { toast } from "react-toastify"
import Spinner from "../../../Spinner"
import { useMutation } from "@tanstack/react-query"
import { TokenModel } from "src/codegen/model"
import { cancelTokensVendingappAppIdTokensCancelPost } from "src/codegen"
import { Button } from "@/components/ui/button"
import { Loader2 } from "lucide-react"

interface Props {
token: Pick<TokenModel, "id">
token: Pick<TokenModel, "token">
appId: string
setState: React.Dispatch<React.SetStateAction<string>>
}
Expand All @@ -21,9 +21,9 @@ const TokenCancelButton: FunctionComponent<Props> = ({
const { t } = useTranslation()

const cancelVendingTokensMutation = useMutation({
mutationKey: ["cancel-token", appId, token.id],
mutationKey: ["cancel-token", appId, token.token],
mutationFn: () => {
return cancelTokensVendingappAppIdTokensCancelPost(appId, [token.id], {
return cancelTokensVendingappAppIdTokensCancelPost(appId, [token.token], {
withCredentials: true,
})
},
Expand All @@ -38,10 +38,6 @@ const TokenCancelButton: FunctionComponent<Props> = ({
},
})

if (cancelVendingTokensMutation.isPending) {
return <Spinner size="s" />
}

// Button is spent after successful use
if (
cancelVendingTokensMutation.isSuccess &&
Expand All @@ -55,7 +51,11 @@ const TokenCancelButton: FunctionComponent<Props> = ({
size="lg"
variant="destructive"
onClick={() => cancelVendingTokensMutation.mutate()}
disabled={cancelVendingTokensMutation.isPending}
>
{cancelVendingTokensMutation.isPending && (
<Loader2 className="animate-spin" />
)}
{t("cancel")}
</Button>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,30 @@ const TokenListItem: FunctionComponent<Props> = ({ open, token, appId }) => {
return (
<>
<DisclosureButton className="flex justify-between rounded-lg border p-2 hover:opacity-80 focus:outline-none focus-visible:ring focus-visible:ring-opacity-75">
<div className="grid w-full grid-cols-3 justify-items-start">
<span>{token.id}</span>
<span>{token.name}</span>
<span>{t(`status-${state}`)}</span>
<div className="flex w-full">
<div>{token.name}</div>
<div className="ms-auto pe-8">{t(`status-${state}`)}</div>
</div>
<HiChevronUp
className={clsx("text-2xl transition", !open && "rotate-180")}
/>
</DisclosureButton>
<DisclosurePanel className="flex flex-wrap justify-between gap-y-4 pe-4 ps-4">
<div className="flex flex-col gap-4">
{token.token && <span>{token.token}</span>}
<span>
<div className="grid w-full xl:grid-cols-3 justify-items-start items-center">
{token.token && <div>{token.token}</div>}
<div>
{t("transaction-summary-created")} {format(token.created, "PP")}
</span>
</div>
<div className="justify-self-end">
{state === "unredeemed" && (
<TokenCancelButton
token={token}
appId={appId}
setState={setState}
/>
)}
</div>
</div>
{state === "unredeemed" && (
<TokenCancelButton token={token} appId={appId} setState={setState} />
)}
</DisclosurePanel>
</>
)
Expand Down

0 comments on commit e2832d9

Please sign in to comment.