Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/api/backend/schemas/discounts/discountSchema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import z from 'zod';

import { discountEligibilities, discountMethods, discountTargets, discountValueTypes } from '../../const';
import {
discountEligibilities,
discountMethods,
discountTargets,
discountValueTypes,
paymentMethods,
} from '../../const';
import { Brand, Category, SearchUser, VariantWithProduct } from '../../types';

export const discountSchema = z.object({
Expand All @@ -21,6 +27,7 @@ export const discountSchema = z.object({
brands: z.array(z.custom<Brand>()).optional(),
eligibility: z.enum(discountEligibilities),
eligibleUsers: z.array(z.custom<SearchUser>()).optional(),
paymentMethods: z.array(z.enum(paymentMethods)).optional(),
});

export type DiscountSchema = z.infer<typeof discountSchema>;
1 change: 1 addition & 0 deletions src/api/backend/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ export interface Discount {
categories: Category[];
brands: Brand[];
eligibleUsers: SearchUser[];
paymentMethods: PaymentMethod[] | null;
createdAt: string;
updatedAt: string;
}
Expand Down
3 changes: 3 additions & 0 deletions src/app/(hydration)/(base)/discounts/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DiscountApplicability,
DiscountEligibility,
DiscountStatus,
DiscountPaymentMethods,
} from '@/components';
import { useDiscountQuery } from '@/hooks';
import { PagePropsWithParams } from '@/app/types';
Expand Down Expand Up @@ -44,6 +45,8 @@ export default async function EditDiscount(props: PagePropsWithParams<{ id: stri

<DiscountApplicability />

<DiscountPaymentMethods />

<DiscountEligibility />
</div>

Expand Down
3 changes: 3 additions & 0 deletions src/app/(hydration)/(base)/discounts/add/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
DiscountRestrictions,
DiscountApplicability,
DiscountEligibility,
DiscountPaymentMethods,
} from '@/components';

export const metadata: Metadata = { title: 'Gamers Core | Discounts | Add Discount' };
Expand All @@ -24,6 +25,8 @@ export default async function AddDiscount() {

<DiscountApplicability />

<DiscountPaymentMethods />

<DiscountEligibility />
</div>

Expand Down
1 change: 1 addition & 0 deletions src/components/discounts/DiscountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ const mapDiscountToSchema = (discount: Discount): DiscountSchema => ({
usageLimitPerUser: discount.usageLimitPerUser ?? undefined,
startsAt: discount.startsAt ?? undefined,
expiresAt: discount.expiresAt ?? undefined,
paymentMethods: discount.paymentMethods ?? undefined,
});
61 changes: 61 additions & 0 deletions src/components/discounts/DiscountPaymentMethods.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';

import { Controller, useFormContext } from 'react-hook-form';

import { paymentMethods, DiscountSchema } from '@/api';

import { Field, FieldError, FieldGroup } from '../ui';
import { Button } from '../Button';

export const DiscountPaymentMethods = () => {
const form = useFormContext<DiscountSchema>();

return (
<section className="bg-sidebar p-4 rounded-lg flex flex-col gap-6">
<h3 className="text-lg font-semibold">Payment Methods</h3>

<FieldGroup className="flex flex-col gap-2">
<Controller
name="paymentMethods"
control={form.control}
render={({ field, fieldState }) => {
const selected = field.value ?? [];

const toggle = (method: (typeof paymentMethods)[number]) => {
const next = selected.includes(method) ? selected.filter((m) => m !== method) : [...selected, method];

field.onChange(next.length ? next : undefined);
};

return (
<>
<Field className="flex flex-row flex-wrap gap-2 items-center min-w-auto">
{paymentMethods.map((method) => (
<Button
key={method}
className="capitalize flex-1 h-10 max-w-none min-w-40 font-semibold text-base"
onClick={() => toggle(method)}
variant={selected.includes(method) ? 'default' : 'secondary'}
>
{method.replaceAll('_', ' ')}
</Button>
))}
</Field>

<p className="text-xs text-muted-foreground">
{selected.length
? 'Discount only applies to selected payment methods.'
: 'Applies to all payment methods.'}
</p>

{fieldState.invalid && (
<FieldError className="text-sm/normal md:text-sm/relaxed" errors={[fieldState.error]} />
)}
</>
);
}}
/>
</FieldGroup>
</section>
);
};
1 change: 1 addition & 0 deletions src/components/discounts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export * from './DiscountRestrictions';
export * from './DiscountApplicability';
export * from './DiscountEligibility';
export * from './DiscountUsagesModal';
export * from './DiscountPaymentMethods';
Loading