Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
632bfe2
ported over modules
pmltechpile Jun 8, 2025
145d4fb
ported over links, admin sdk and subscribers
pmltechpile Jun 8, 2025
eeb95be
fix build errors
pmltechpile Jun 8, 2025
7593520
cleanup
pmltechpile Jun 8, 2025
72cc90f
porting more changes over: admin menu component and hooks
pmltechpile Jun 9, 2025
448a31a
updated menu and forms
pmltechpile Jun 9, 2025
9938f33
refactor: menu list listing and routing fix. Need to work on adding/e…
pmltechpile Jul 12, 2025
810e28b
fix: menu updates
pmltechpile Jul 12, 2025
ed21b42
feat: courses support for menus
pmltechpile Jul 12, 2025
3fa824d
feat: chefs events on admin page
pmltechpile Jul 16, 2025
310d081
feat: docs for implementation plan for storefront
pmltechpile Jul 16, 2025
452fcd6
Phase 1 of storefront support - store APIs
pmltechpile Jul 16, 2025
7a749bf
extending sdk for storefront
pmltechpile Jul 16, 2025
f163731
feat: homepage refactor, menu carousel, FAQ page
pmltechpile Jul 17, 2025
1c8933d
wip: clinet event requested
pmltechpile Jul 17, 2025
5b05b86
wip: request flow completion
pmltechpile Jul 17, 2025
08070df
feat: customer request flow creates a chef event and shows confirmation
pmltechpile Jul 20, 2025
f3771f5
feat: request notification sent to chef and setup for confirmation to…
pmltechpile Jul 21, 2025
c8f263d
refactor: update to implementation doc
pmltechpile Jul 21, 2025
a8fe536
Updated implementation doc for chef approval workflow
pmltechpile Jul 21, 2025
f63fe42
wip: chef acceptance flow; creating event product and sending email s…
pmltechpile Jul 22, 2025
cc15823
updated email accepted to correct template
pmltechpile Jul 26, 2025
82bf484
updated implementation plan
pmltechpile Jul 26, 2025
3a41efa
feat: added implementation plan for resend
pmltechpile Jul 26, 2025
025f3e6
feat: resend integration implementation
pmltechpile Jul 26, 2025
6c0274a
feat: event product details page
pmltechpile Jul 26, 2025
30e9226
feat: adding to cart working
pmltechpile Jul 27, 2025
1540853
wip: order is being placed but with wrong amount
pmltechpile Jul 28, 2025
86e1c83
feat: correct price is debited for ticket
pmltechpile Jul 29, 2025
dc0c75b
fix: checkout flow purchase button and quantity count
pmltechpile Jul 29, 2025
59f5dca
updated documentation
pmltechpile Jul 29, 2025
92cadbb
docs: added implementation plan for email tooling feature
pmltechpile Jul 29, 2025
be2792a
feat: changing copy to chef velez
pmltechpile Jul 30, 2025
b06d51f
menu seed script and support
pmltechpile Jul 30, 2025
ee5af16
feat: resend event details chef admin tooling
pmltechpile Jul 31, 2025
64e6875
fix: fixed confirmation email on chef acceptance
pmltechpile Jul 31, 2025
d647651
fix: event product created with sales channel assigned
pmltechpile Aug 4, 2025
da73209
fix: associating correct inventory to event product
pmltechpile Aug 4, 2025
2cea95c
cleanup
pmltechpile Aug 4, 2025
4089bef
cleanup
pmltechpile Aug 4, 2025
179f361
feat: API to create link between api key and saleschannel, creating e…
pmltechpile Aug 5, 2025
3b58da6
fix: product created correctly and purchaseable on chef acceptance
pmltechpile Aug 6, 2025
cb72cfc
feat: event request form changes
pmltechpile Aug 9, 2025
6b04e1d
fix: updated event request form
pmltechpile Aug 10, 2025
45dc7e7
fix: homepage updates and tweaks
pmltechpile Aug 10, 2025
134885c
feat: homepage updates
pmltechpile Aug 10, 2025
e6ec511
refactor: more homepage cleanup
pmltechpile Aug 11, 2025
c13709f
wip: Menu images support for backend; need to support frontend
pmltechpile Aug 13, 2025
5ed13a7
wip: menu image support on the frontend
pmltechpile Aug 13, 2025
6c7350c
wip: calendar view for chef events
pmltechpile Aug 17, 2025
ea9358d
feat: chef event calendar view no list
pmltechpile Aug 17, 2025
950dcfe
feat: deployment plan
pmltechpile Aug 20, 2025
c786400
feat: deployment setup
pmltechpile Aug 20, 2025
0be89e2
fix: build issues
pmltechpile Aug 20, 2025
c64c1c5
testing build fix
pmltechpile Aug 20, 2025
3865cb2
more testing
pmltechpile Aug 20, 2025
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
56 changes: 56 additions & 0 deletions .cursor/rules/medusa-development.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ You are an expert in Medusa v2, TypeScript, Node.js, PostgreSQL, and modern e-co

### Framework Structure
- **Modules**: Self-contained packages with domain-specific functionality
- **Service Factory**: More detail into services
- **Services**: Business logic layer with dependency injection
- **API Routes**: RESTful endpoints in `/api/admin` and `/api/store`
- **Workflows**: Multi-step business processes with error handling
Expand Down Expand Up @@ -55,6 +56,61 @@ class MyService extends MedusaService({
}
```

### Service Factory

The Service Factory (`MedusaService`) is a powerful utility that automatically generates a set of standard CRUD methods for your service. When you extend `MedusaService`, your service automatically gets the following methods for each model you register:

```typescript
// Service pattern with Service Factory
import { MedusaService } from "@medusajs/framework/utils"
import { Menu } from "./models/menu"

class MenuModuleService extends MedusaService({
Menu
}) {
// The service automatically gets these methods:
// - createMenus(data: CreateMenuInput): Promise<Menu>
// - retrieveMenu(id: string): Promise<Menu>
// - listMenus(filters?: FilterableMenuProps): Promise<Menu[]>
// - listAndCountMenus(filters?: FilterableMenuProps): Promise<[Menu[], number]>
// - updateMenus(data: UpdateMenuInput): Promise<Menu>
// - deleteMenus(id: string): Promise<void>
// - softDeleteMenus(id: string): Promise<void>
// - restoreMenus(id: string): Promise<Menu>
}
```

The generated method names follow the pattern `{operationName}_{dataModelName}`, where:
- `{operationName}` is the operation (create, retrieve, list, etc.)
- `{dataModelName}` is the pascal-case version of the model key, pluralized for all operations except `retrieve`

For example, if you register a model named `Post`, you get methods like:
- `createPosts`
- `retrievePost`
- `listPosts`
- `listAndCountPosts`
- `updatePosts`
- `deletePosts`
- `softDeletePosts`
- `restorePosts`

You can still add custom methods to your service while having access to these generated methods:

```typescript
class MenuModuleService extends MedusaService({
Menu
}) {
// Custom method
async getActiveMenus(): Promise<Menu[]> {
return await this.listMenus({
status: "active"
})
}
}
```

The Service Factory provides a consistent interface for data operations while allowing you to extend functionality as needed.

### API Route Patterns
```typescript
// Admin API route
Expand Down
38 changes: 37 additions & 1 deletion apps/medusa/medusa-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ const REDIS_URL = process.env.REDIS_URL;
const STRIPE_API_KEY = process.env.STRIPE_API_KEY;
const IS_TEST = process.env.NODE_ENV === 'test';

const customModules = [
{
resolve: './src/modules/menu',
options: {},
},
{
resolve: './src/modules/chef-event',
options: {},
},
]

const cacheModule = IS_TEST
? { resolve: '@medusajs/medusa/cache-inmemory' }
: {
Expand Down Expand Up @@ -35,15 +46,33 @@ const workflowEngineModule = IS_TEST
},
};

const notificationModule = {
resolve: "@medusajs/medusa/notification",
options: {
providers: [
{
resolve: "./src/modules/resend",
id: "resend",
options: {
channels: ["email"],
api_key: process.env.RESEND_API_KEY,
from: process.env.RESEND_FROM_EMAIL,
},
},
],
},
};

module.exports = defineConfig({
projectConfig: {
databaseUrl: process.env.DATABASE_URL,
databaseDriverOptions: {
ssl: false,
},
redisUrl: REDIS_URL,

redisPrefix: process.env.REDIS_PREFIX,
// ADD WORKER MODE CONFIGURATION
workerMode: process.env.MEDUSA_WORKER_MODE as "shared" | "worker" | "server",
http: {
storeCors: process.env.STORE_CORS || '',
adminCors: process.env.ADMIN_CORS || '',
Expand All @@ -59,6 +88,7 @@ module.exports = defineConfig({
},
],
modules: [
...customModules,
{
resolve: '@medusajs/medusa/payment',
options: {
Expand All @@ -76,8 +106,11 @@ module.exports = defineConfig({
cacheModule,
eventBusModule,
workflowEngineModule,
notificationModule,
],
admin: {
// ADD ADMIN DISABLE CONFIGURATION
disable: process.env.DISABLE_MEDUSA_ADMIN === "true",
backendUrl: process.env.ADMIN_BACKEND_URL,
vite: () => {
return {
Expand All @@ -88,3 +121,6 @@ module.exports = defineConfig({
},
},
});



11 changes: 10 additions & 1 deletion apps/medusa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
"nukedb": "docker compose down -v && docker compose up -d",
"build": "medusa build",
"seed": "medusa exec ./src/scripts/seed.ts",
"seed:menus": "medusa exec ./src/scripts/seed/menus.ts",
"start": "medusa start",
"dev": "medusa develop",
"dev:email": "email dev --dir ./src/modules/resend/emails",
"sync": "medusa db:sync-links",
"migrate:prod": "medusa db:migrate",
"start:prod": "medusa start",
"seed:prod": "medusa exec ./src/scripts/seed.js && yarn add-user:prod",
"add-user:prod": "medusa user --email admin@medusa-test.com --password supersecret && medusa user --email admin@lambdacurry.dev --password password",
"migrate": "medusa db:migrate",
"predeploy": "medusa db:migrate",
"test:integration:http": "TEST_TYPE=integration:http NODE_OPTIONS=--experimental-vm-modules jest --silent=false --runInBand --forceExit",
"test:integration:modules": "TEST_TYPE=integration:modules NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
"test:unit": "TEST_TYPE=unit NODE_OPTIONS=--experimental-vm-modules jest --silent --runInBand --forceExit",
Expand All @@ -43,15 +46,20 @@
"@mikro-orm/knex": "6.4.3",
"@mikro-orm/migrations": "6.4.3",
"@mikro-orm/postgresql": "6.4.3",
"@react-email/components": "^0.3.2",
"@types/luxon": "^3.6.2",
"awilix": "^8.0.1",
"pg": "^8.13.0"
"date-fns": "^4.1.0",
"pg": "^8.13.0",
"resend": "^4.7.0"
},
"devDependencies": {
"@medusajs/test-utils": "2.7.0",
"@mikro-orm/cli": "6.4.3",
"@mikro-orm/core": "6.4.3",
"@mikro-orm/migrations": "6.4.3",
"@mikro-orm/postgresql": "6.4.3",
"@react-email/preview-server": "4.2.4",
"@stdlib/number-float64-base-normalize": "0.0.8",
"@swc/core": "1.5.7",
"@swc/jest": "^0.2.36",
Expand All @@ -62,6 +70,7 @@
"@types/react": "^18.3.2",
"jest": "^29.7.0",
"prop-types": "^15.8.1",
"react-email": "^4.2.4",
"ts-node": "^10.9.2",
"typescript": "^5.7.3",
"yalc": "^1.0.0-pre.53"
Expand Down
121 changes: 121 additions & 0 deletions apps/medusa/src/admin/hooks/chef-events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { sdk } from '../../sdk'
import type {
AdminListChefEventsQuery,
AdminCreateChefEventDTO,
AdminUpdateChefEventDTO,
AdminChefEventDTO,
AdminChefEventsResponse,
AdminAcceptChefEventDTO,
AdminRejectChefEventDTO,
AdminResendEventEmailDTO
} from '../../sdk/admin/admin-chef-events'

const QUERY_KEY = ['chef-events']

export const useAdminListChefEvents = (query: AdminListChefEventsQuery = {}) => {
return useQuery<AdminChefEventsResponse>({
queryKey: [...QUERY_KEY, query],
placeholderData: (previousData) => previousData,
queryFn: async () => {
return sdk.admin.chefEvents.list(query)
},
})
}

export const useAdminRetrieveChefEvent = (id: string) => {
return useQuery<AdminChefEventDTO>({
queryKey: [...QUERY_KEY, id],
queryFn: async () => {
return sdk.admin.chefEvents.retrieve(id)
},
})
}

export const useAdminCreateChefEventMutation = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (data: AdminCreateChefEventDTO) => {
return await sdk.admin.chefEvents.create(data)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
},
})
}

export const useAdminUpdateChefEventMutation = (id: string) => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (data: AdminUpdateChefEventDTO) => {
return await sdk.admin.chefEvents.update(id, data)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
queryClient.invalidateQueries({ queryKey: [...QUERY_KEY, id] })
},
})
}

export const useAdminDeleteChefEventMutation = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (id: string) => {
return await sdk.admin.chefEvents.delete(id)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
},
})
}

export const useAdminAcceptChefEventMutation = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async ({ id, data }: { id: string; data?: AdminAcceptChefEventDTO }) => {
return await sdk.admin.chefEvents.accept(id, data || {})
},
onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
queryClient.invalidateQueries({ queryKey: [...QUERY_KEY, variables.id] })
},
})
}

export const useAdminRejectChefEventMutation = () => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async ({ id, data }: { id: string; data: AdminRejectChefEventDTO }) => {
return await sdk.admin.chefEvents.reject(id, data)
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
},
})
}

/**
* Hook for resending event emails
*/
export const useAdminResendEventEmailMutation = () => {
const queryClient = useQueryClient()

return useMutation({
mutationFn: async ({ chefEventId, ...data }: { chefEventId: string } & AdminResendEventEmailDTO) => {
return await sdk.admin.chefEvents.resendEmail(chefEventId, data)
},
onSuccess: (data, variables) => {
queryClient.invalidateQueries({ queryKey: QUERY_KEY })
queryClient.invalidateQueries({ queryKey: [...QUERY_KEY, variables.chefEventId] })
},
})
}

export const useAdminGetMenuProducts = () => {
return useQuery({
queryKey: [...QUERY_KEY, 'menu-products'],
queryFn: async () => {
return sdk.admin.chefEvents.getMenuProducts()
},
})
}
Loading