Skip to content
This repository has been archived by the owner on Sep 24, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4 from commercelayer/enhance-rule-builder
Browse files Browse the repository at this point in the history
Improve rule builder
  • Loading branch information
marcomontalbano authored Jan 30, 2024
2 parents ef6c4c6 + ac03384 commit 4f67fcd
Show file tree
Hide file tree
Showing 31 changed files with 1,320 additions and 3,838 deletions.
4 changes: 2 additions & 2 deletions packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"prepare": "touch ./public/config.local.js"
},
"dependencies": {
"@commercelayer/app-elements": "^1.11.1",
"@commercelayer/sdk": "5.28.0",
"@commercelayer/app-elements": "^1.12.5",
"@commercelayer/sdk": "5.30.0",
"@hookform/resolvers": "^3.3.4",
"lodash": "^4.17.21",
"react": "^18.2.0",
Expand Down
67 changes: 30 additions & 37 deletions packages/app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,8 @@ import { SWRConfig } from 'swr'
import { Route, Router, Switch } from 'wouter'
import { appRoutes } from './data/routes'

const HomePage = lazy(async () => await import('#pages/HomePage'))
const PromotionListPage = lazy(
async () => await import('#pages/PromotionListPage')
)
const FiltersPage = lazy(async () => await import('#pages/FiltersPage'))
const PromotionDetailsPage = lazy(
async () => await import('#pages/PromotionDetailsPage')
)
const EditPromotionPage = lazy(
async () => await import('#pages/EditPromotionPage')
)
const NewSelectTypePage = lazy(
async () => await import('#pages/NewSelectTypePage')
)
const NewPromotionPage = lazy(
async () => await import('#pages/NewPromotionPage')
)
const PromotionConditionsPage = lazy(
async () => await import('#pages/PromotionConditionsPage')
)
const NewPromotionConditionPage = lazy(
async () => await import('#pages/NewPromotionConditionPage')
)

const isDev = Boolean(import.meta.env.DEV)

const basePath =
import.meta.env.PUBLIC_PROJECT_PATH != null
? `/${import.meta.env.PUBLIC_PROJECT_PATH}`
Expand Down Expand Up @@ -63,38 +40,54 @@ export function App(): JSX.Element {
<Suspense fallback={<LoadingPage />}>
<Router base={basePath}>
<Switch>
<Route path={appRoutes.home.path} component={HomePage} />
<Route
path={appRoutes.list.path}
component={PromotionListPage}
path={appRoutes.home.path}
component={lazy(
async () => await import('#pages/HomePage')
)}
/>
<Route
path={appRoutes.promotionList.path}
component={lazy(
async () => await import('#pages/PromotionListPage')
)}
/>
<Route
path={appRoutes.filters.path}
component={FiltersPage}
component={lazy(
async () => await import('#pages/FiltersPage')
)}
/>
<Route
path={appRoutes.promotionDetails.path}
component={PromotionDetailsPage}
component={lazy(
async () => await import('#pages/PromotionDetailsPage')
)}
/>
<Route
path={appRoutes.editPromotion.path}
component={EditPromotionPage}
component={lazy(
async () => await import('#pages/EditPromotionPage')
)}
/>
<Route
path={appRoutes.newSelectType.path}
component={NewSelectTypePage}
component={lazy(
async () => await import('#pages/NewSelectTypePage')
)}
/>
<Route
path={appRoutes.newPromotion.path}
component={NewPromotionPage}
/>
<Route
path={appRoutes.promotionConditions.path}
component={PromotionConditionsPage}
component={lazy(
async () => await import('#pages/NewPromotionPage')
)}
/>
<Route
path={appRoutes.newPromotionCondition.path}
component={NewPromotionConditionPage}
component={lazy(
async () =>
await import('#pages/NewPromotionConditionPage')
)}
/>
<Route component={ErrorNotFound} />
</Switch>
Expand Down
27 changes: 18 additions & 9 deletions packages/app/src/components/PromotionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ export function PromotionForm({
promotion = await resource.update({ id: promotionId, ...formValues })
} else {
// @ts-expect-error // TODO: I need to fix this
promotion = await resource.create(formValues)

await resource._disable(promotion.id)
promotion = await resource.create({
...formValues,
_disable: true,
reference_origin: 'app-promotions'
})
}

setLocation(
Expand All @@ -91,24 +93,31 @@ export function PromotionForm({
<HookedInputDate name='expires_at' label='Expires on' />
</Grid>
</Spacer>
</Section>
</Spacer>
<Spacer top='14'>
<Section title='Promotion info'>

{/* follows the promotion specific fields */}
<Spacer top='6'>
<HookedInput
type='number'
min={1}
max={100}
name='percentage'
label='Percentage discount'
hint={{
text: 'How much the order subtotal is discounted in percentage.'
text: 'The applied percentage discount.'
}}
/>
</Spacer>
</Section>
</Spacer>
<Spacer top='14'>
<Spacer top='8'>
<Button type='submit' fullWidth>
<Button
type='submit'
fullWidth
disabled={
methods.formState.isSubmitting || !methods.formState.isValid
}
>
{promotionId != null ? 'Update promotion' : 'Create promotion'}
</Button>
</Spacer>
Expand Down
132 changes: 63 additions & 69 deletions packages/app/src/data/dictionaries/promotion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,120 +57,114 @@ export type PromotionDictionary = {
}
}

const genericPromotionOptions = z.object({
name: z.string().min(1),
starts_at: z.date(),
expires_at: z.date()
})

export const promotionDictionary = {
buy_x_pay_y_promotions: {
enable: false,
type: 'buy_x_pay_y_promotions',
slug: 'buy-x-pay-y',
icon: 'stack',
titleList: 'Buy X pay Y',
titleNew: 'buy X pay Y',
form: z.object({
name: z.string().min(1),
percentage1: z
.string()
.min(1)
.transform((p) => parseInt(p)),
startOn: z.date(),
expiresOn: z.date()
})
form: genericPromotionOptions.merge(
z.object({
x: z.number(),
y: z.number(),
sku_list: z.object({ type: z.literal('sku_lists'), id: z.string() })
})
)
},
external_promotions: {
enable: false,
type: 'external_promotions',
slug: 'external',
icon: 'stack',
icon: 'linkSimple',
titleList: 'External promotion',
titleNew: 'external promotion',
form: z.object({
name: z.string().min(1),
percentage: z
.string()
.min(1)
.transform((p) => parseInt(p)),
startOn: z.date(),
expiresOn: z.date()
})
form: genericPromotionOptions.merge(z.object({}))
},
fixed_amount_promotions: {
enable: false,
type: 'fixed_amount_promotions',
slug: 'fixed-amount',
icon: 'stack',
icon: 'currencyEur',
titleList: 'Fixed amount discount',
titleNew: 'fixed amount discount',
form: z.object({
name: z.string().min(1),
fixed_amount_cents: z
.string()
.min(1)
.transform((p) => parseInt(p)),
starts_at: z.date(),
expires_at: z.date()
})
form: genericPromotionOptions.merge(
z.object({
fixed_amount_cents: z
.string()
.min(1)
.transform((p) => parseInt(p))
})
)
},
fixed_price_promotions: {
enable: false,
type: 'fixed_price_promotions',
slug: 'fixed-price',
icon: 'stack',
icon: 'pushPin',
titleList: 'Fixed price',
titleNew: 'fixed price',
form: z.object({
name: z.string().min(1),
percentage: z
.string()
.min(1)
.transform((p) => parseInt(p)),
startOn: z.date(),
expiresOn: z.date()
})
form: genericPromotionOptions.merge(z.object({}))
},
free_gift_promotions: {
enable: false,
type: 'free_gift_promotions',
slug: 'free-gift',
icon: 'stack',
icon: 'gift',
titleList: 'Free gift',
titleNew: 'free gift',
form: z.object({
name: z.string().min(1),
percentage: z
.string()
.min(1)
.transform((p) => parseInt(p)),
startOn: z.date(),
expiresOn: z.date()
})
form: genericPromotionOptions.merge(z.object({}))
},
free_shipping_promotions: {
enable: false,
type: 'free_shipping_promotions',
slug: 'free-shipping',
icon: 'truck',
titleList: 'Free shipping',
titleNew: 'free shipping',
form: z.object({
name: z.string().min(1),
percentage: z
.string()
.min(1)
.transform((p) => parseInt(p)),
startOn: z.date(),
expiresOn: z.date()
})
form: genericPromotionOptions.merge(z.object({}))
},
percentage_discount_promotions: {
enable: true,
type: 'percentage_discount_promotions',
slug: 'percentage-discount',
icon: 'stack',
icon: 'percent',
titleList: 'Percentage discount',
titleNew: 'percentage discount',
form: z.object({
name: z.string().min(1),
percentage: z
.number()
.or(z.string().min(1))
.transform((p) => parseInt(p.toString())),
starts_at: z.date(),
expires_at: z.date()
})
form: genericPromotionOptions.merge(
z.object({
percentage: z
.number()
.max(100)
.or(
z
.string()
.min(1)
.regex(/^[1-9][0-9]?$|^100$/)
)
.transform((p) => parseInt(p.toString()))
})
)
}
} as const
} as const satisfies Record<
string,
{
enable: boolean
type: string
slug: string
icon: IconProps['name']
titleList: string
titleNew: string
form: z.AnyZodObject
}
>

// HELPER

Expand Down
3 changes: 3 additions & 0 deletions packages/app/src/data/isValid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isDefined<T>(value: T | undefined | null): value is T {
return value != null
}
Loading

0 comments on commit 4f67fcd

Please sign in to comment.