@open-mercato/scheduler 0.6.5-develop.4788.1.a3e2520ec0 → 0.6.5-develop.4790.1.bffb4fd44b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,7 @@ import { useConfirmDialog } from "@open-mercato/ui/backend/confirm-dialog";
13
13
  import { useT } from "@open-mercato/shared/lib/i18n/context";
14
14
  import { useOrganizationScopeVersion } from "@open-mercato/shared/lib/frontend/useOrganizationScope";
15
15
  import { formatDateTime } from "@open-mercato/shared/lib/time";
16
+ import { ListEmptyState } from "@open-mercato/ui/backend/filters/ListEmptyState";
16
17
  function mapApiItem(item) {
17
18
  const id = typeof item.id === "string" ? item.id : null;
18
19
  if (!id) return null;
@@ -138,7 +139,7 @@ function SchedulerPage() {
138
139
  cell: ({ row }) => {
139
140
  const target = row.original.targetType === "queue" ? row.original.targetQueue : row.original.targetCommand;
140
141
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
141
- /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 capitalize", children: row.original.targetType }),
142
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground capitalize", children: row.original.targetType }),
142
143
  /* @__PURE__ */ jsx("span", { className: "text-sm", children: target || "-" })
143
144
  ] });
144
145
  }
@@ -203,6 +204,14 @@ function SchedulerPage() {
203
204
  data: rows,
204
205
  onRowClick: (row) => router.push(`/backend/config/scheduled-jobs/${row.id}`),
205
206
  rowActions: (row) => /* @__PURE__ */ jsx(RowActions, { items: rowActions(row) }),
207
+ emptyState: /* @__PURE__ */ jsx(
208
+ ListEmptyState,
209
+ {
210
+ entityName: t("scheduler.title", "Scheduled Jobs"),
211
+ createHref: "/backend/config/scheduled-jobs/new",
212
+ createLabel: t("scheduler.action.create", "New Schedule")
213
+ }
214
+ ),
206
215
  pagination: { page, pageSize, total, totalPages, onPageChange: setPage },
207
216
  isLoading,
208
217
  searchValue: search,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../../src/modules/scheduler/backend/config/scheduled-jobs/page.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\n\ntype ScheduleRow = {\n id: string\n name: string\n description?: string | null\n scopeType: 'system' | 'organization' | 'tenant'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n targetType: 'queue' | 'command'\n targetQueue?: string | null\n targetCommand?: string | null\n isEnabled: boolean\n sourceType: 'user' | 'module'\n sourceModule?: string | null\n nextRunAt?: string | null\n lastRunAt?: string | null\n}\n\ntype SchedulesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n page?: number\n totalPages?: number\n}\n\nfunction mapApiItem(item: Record<string, unknown>): ScheduleRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n\n return {\n id,\n name: typeof item.name === 'string' ? item.name : '',\n description: typeof item.description === 'string' ? item.description : null,\n scopeType: (item.scopeType === 'system' || item.scopeType === 'organization' || item.scopeType === 'tenant')\n ? item.scopeType\n : 'tenant',\n scheduleType: (item.scheduleType === 'cron' || item.scheduleType === 'interval')\n ? item.scheduleType\n : 'cron',\n scheduleValue: typeof item.scheduleValue === 'string' ? item.scheduleValue : '',\n timezone: typeof item.timezone === 'string' ? item.timezone : 'UTC',\n targetType: (item.targetType === 'queue' || item.targetType === 'command')\n ? item.targetType\n : 'queue',\n targetQueue: typeof item.targetQueue === 'string' ? item.targetQueue : null,\n targetCommand: typeof item.targetCommand === 'string' ? item.targetCommand : null,\n isEnabled: item.isEnabled === true,\n sourceType: (item.sourceType === 'user' || item.sourceType === 'module')\n ? item.sourceType\n : 'user',\n sourceModule: typeof item.sourceModule === 'string' ? item.sourceModule : null,\n nextRunAt: typeof item.nextRunAt === 'string' ? item.nextRunAt : null,\n lastRunAt: typeof item.lastRunAt === 'string' ? item.lastRunAt : null,\n }\n}\n\n\nexport default function SchedulerPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const [rows, setRows] = React.useState<ScheduleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n\n const fetchSchedules = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n pageSize: pageSize.toString(),\n })\n if (search) params.set('search', search)\n\n const { result } = await apiCallOrThrow<SchedulesResponse>(\n `/api/scheduler/jobs?${params.toString()}`\n )\n\n const items = result?.items ?? []\n const mapped = items.map(mapApiItem).filter((x): x is ScheduleRow => x !== null)\n setRows(mapped)\n setTotal(result?.total ?? 0)\n setTotalPages(result?.totalPages ?? 1)\n } catch (error) {\n flash(t('scheduler.error.fetch_failed', 'Failed to load schedules'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [page, pageSize, search, scopeVersion, t])\n\n React.useEffect(() => {\n fetchSchedules()\n }, [fetchSchedules])\n\n const handleDelete = React.useCallback(\n async (row: ScheduleRow) => {\n const confirmed = await confirm({\n title: t('scheduler.confirm.delete', 'Are you sure you want to delete this schedule?'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n try {\n await apiCallOrThrow(`/api/scheduler/jobs`, {\n method: 'DELETE',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.deleted', 'Schedule deleted successfully'), 'success')\n fetchSchedules()\n } catch (error) {\n flash(t('scheduler.error.delete_failed', 'Failed to delete schedule'), 'error')\n }\n },\n [confirm, t, fetchSchedules]\n )\n\n const handleTrigger = React.useCallback(\n async (row: ScheduleRow) => {\n try {\n await apiCallOrThrow(`/api/scheduler/trigger`, {\n method: 'POST',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.triggered', 'Schedule triggered successfully'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('scheduler.error.trigger_failed', 'Failed to trigger schedule')\n flash(message, 'error')\n }\n },\n [t]\n )\n\n const columns = React.useMemo<ColumnDef<ScheduleRow>[]>(\n () => [\n {\n id: 'name',\n accessorKey: 'name',\n header: t('scheduler.field.name', 'Name'),\n cell: ({ row }) => (\n <span className=\"font-medium\">{row.original.name}</span>\n ),\n },\n {\n id: 'scheduleType',\n accessorKey: 'scheduleType',\n header: t('scheduler.field.schedule_type', 'Type'),\n cell: ({ row }) => (\n <span className=\"capitalize\">{row.original.scheduleType}</span>\n ),\n },\n {\n id: 'scheduleValue',\n accessorKey: 'scheduleValue',\n header: t('scheduler.field.schedule', 'Schedule'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {row.original.scheduleValue}\n </span>\n ),\n },\n {\n id: 'targetType',\n accessorKey: 'targetType',\n header: t('scheduler.field.target', 'Target'),\n cell: ({ row }) => {\n const target = row.original.targetType === 'queue'\n ? row.original.targetQueue\n : row.original.targetCommand\n return (\n <div className=\"flex flex-col\">\n <span className=\"text-xs text-gray-500 capitalize\">{row.original.targetType}</span>\n <span className=\"text-sm\">{target || '-'}</span>\n </div>\n )\n },\n },\n {\n id: 'nextRunAt',\n accessorKey: 'nextRunAt',\n header: t('scheduler.field.next_run', 'Next Run'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateTime(row.original.nextRunAt) || '-'}\n </span>\n ),\n },\n {\n id: 'isEnabled',\n accessorKey: 'isEnabled',\n header: t('scheduler.field.active', 'Active'),\n cell: ({ row }) => <BooleanIcon value={row.original.isEnabled} />,\n },\n {\n id: 'sourceType',\n accessorKey: 'sourceType',\n header: t('scheduler.field.source', 'Source'),\n cell: ({ row }) => (\n <span className=\"text-xs capitalize\">\n {row.original.sourceType}\n {row.original.sourceModule && ` (${row.original.sourceModule})`}\n </span>\n ),\n },\n ],\n [t]\n )\n\n const rowActions = React.useCallback(\n (row: ScheduleRow): RowActionItem[] => [\n {\n id: 'view',\n label: t('scheduler.action.view', 'View Details'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}`),\n },\n {\n id: 'edit',\n label: t('scheduler.action.edit', 'Edit'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}/edit`),\n },\n {\n id: 'trigger',\n label: t('scheduler.action.trigger', 'Run Now'),\n onSelect: () => handleTrigger(row),\n },\n {\n id: 'delete',\n label: t('scheduler.action.delete', 'Delete'),\n onSelect: () => handleDelete(row),\n destructive: true,\n },\n ],\n [t, router, handleDelete, handleTrigger]\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<ScheduleRow>\n title={t('scheduler.title', 'Scheduled Jobs')}\n actions={\n <Button onClick={() => router.push('/backend/config/scheduled-jobs/new')}>\n {t('scheduler.action.create', 'New Schedule')}\n </Button>\n }\n columns={columns}\n data={rows}\n onRowClick={(row) => router.push(`/backend/config/scheduled-jobs/${row.id}`)}\n rowActions={(row) => <RowActions items={rowActions(row)} />}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('scheduler.search.placeholder', 'Search schedules...')}\n refreshButton={{\n label: t('scheduler.action.refresh', 'Refresh'),\n onRefresh: fetchSchedules,\n }}\n />\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { Page, PageBody } from '@open-mercato/ui/backend/Page'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'\nimport type { ColumnDef } from '@tanstack/react-table'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { RowActions, type RowActionItem } from '@open-mercato/ui/backend/RowActions'\nimport { apiCallOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'\n\ntype ScheduleRow = {\n id: string\n name: string\n description?: string | null\n scopeType: 'system' | 'organization' | 'tenant'\n scheduleType: 'cron' | 'interval'\n scheduleValue: string\n timezone: string\n targetType: 'queue' | 'command'\n targetQueue?: string | null\n targetCommand?: string | null\n isEnabled: boolean\n sourceType: 'user' | 'module'\n sourceModule?: string | null\n nextRunAt?: string | null\n lastRunAt?: string | null\n}\n\ntype SchedulesResponse = {\n items?: Array<Record<string, unknown>>\n total?: number\n page?: number\n totalPages?: number\n}\n\nfunction mapApiItem(item: Record<string, unknown>): ScheduleRow | null {\n const id = typeof item.id === 'string' ? item.id : null\n if (!id) return null\n\n return {\n id,\n name: typeof item.name === 'string' ? item.name : '',\n description: typeof item.description === 'string' ? item.description : null,\n scopeType: (item.scopeType === 'system' || item.scopeType === 'organization' || item.scopeType === 'tenant')\n ? item.scopeType\n : 'tenant',\n scheduleType: (item.scheduleType === 'cron' || item.scheduleType === 'interval')\n ? item.scheduleType\n : 'cron',\n scheduleValue: typeof item.scheduleValue === 'string' ? item.scheduleValue : '',\n timezone: typeof item.timezone === 'string' ? item.timezone : 'UTC',\n targetType: (item.targetType === 'queue' || item.targetType === 'command')\n ? item.targetType\n : 'queue',\n targetQueue: typeof item.targetQueue === 'string' ? item.targetQueue : null,\n targetCommand: typeof item.targetCommand === 'string' ? item.targetCommand : null,\n isEnabled: item.isEnabled === true,\n sourceType: (item.sourceType === 'user' || item.sourceType === 'module')\n ? item.sourceType\n : 'user',\n sourceModule: typeof item.sourceModule === 'string' ? item.sourceModule : null,\n nextRunAt: typeof item.nextRunAt === 'string' ? item.nextRunAt : null,\n lastRunAt: typeof item.lastRunAt === 'string' ? item.lastRunAt : null,\n }\n}\n\n\nexport default function SchedulerPage() {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const router = useRouter()\n const [rows, setRows] = React.useState<ScheduleRow[]>([])\n const [page, setPage] = React.useState(1)\n const [pageSize] = React.useState(20)\n const [total, setTotal] = React.useState(0)\n const [totalPages, setTotalPages] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const [isLoading, setIsLoading] = React.useState(false)\n const scopeVersion = useOrganizationScopeVersion()\n\n const fetchSchedules = React.useCallback(async () => {\n setIsLoading(true)\n try {\n const params = new URLSearchParams({\n page: page.toString(),\n pageSize: pageSize.toString(),\n })\n if (search) params.set('search', search)\n\n const { result } = await apiCallOrThrow<SchedulesResponse>(\n `/api/scheduler/jobs?${params.toString()}`\n )\n\n const items = result?.items ?? []\n const mapped = items.map(mapApiItem).filter((x): x is ScheduleRow => x !== null)\n setRows(mapped)\n setTotal(result?.total ?? 0)\n setTotalPages(result?.totalPages ?? 1)\n } catch (error) {\n flash(t('scheduler.error.fetch_failed', 'Failed to load schedules'), 'error')\n setRows([])\n setTotal(0)\n setTotalPages(1)\n } finally {\n setIsLoading(false)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [page, pageSize, search, scopeVersion, t])\n\n React.useEffect(() => {\n fetchSchedules()\n }, [fetchSchedules])\n\n const handleDelete = React.useCallback(\n async (row: ScheduleRow) => {\n const confirmed = await confirm({\n title: t('scheduler.confirm.delete', 'Are you sure you want to delete this schedule?'),\n variant: 'destructive',\n })\n if (!confirmed) {\n return\n }\n\n try {\n await apiCallOrThrow(`/api/scheduler/jobs`, {\n method: 'DELETE',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.deleted', 'Schedule deleted successfully'), 'success')\n fetchSchedules()\n } catch (error) {\n flash(t('scheduler.error.delete_failed', 'Failed to delete schedule'), 'error')\n }\n },\n [confirm, t, fetchSchedules]\n )\n\n const handleTrigger = React.useCallback(\n async (row: ScheduleRow) => {\n try {\n await apiCallOrThrow(`/api/scheduler/trigger`, {\n method: 'POST',\n body: JSON.stringify({ id: row.id }),\n })\n flash(t('scheduler.success.triggered', 'Schedule triggered successfully'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : t('scheduler.error.trigger_failed', 'Failed to trigger schedule')\n flash(message, 'error')\n }\n },\n [t]\n )\n\n const columns = React.useMemo<ColumnDef<ScheduleRow>[]>(\n () => [\n {\n id: 'name',\n accessorKey: 'name',\n header: t('scheduler.field.name', 'Name'),\n cell: ({ row }) => (\n <span className=\"font-medium\">{row.original.name}</span>\n ),\n },\n {\n id: 'scheduleType',\n accessorKey: 'scheduleType',\n header: t('scheduler.field.schedule_type', 'Type'),\n cell: ({ row }) => (\n <span className=\"capitalize\">{row.original.scheduleType}</span>\n ),\n },\n {\n id: 'scheduleValue',\n accessorKey: 'scheduleValue',\n header: t('scheduler.field.schedule', 'Schedule'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {row.original.scheduleValue}\n </span>\n ),\n },\n {\n id: 'targetType',\n accessorKey: 'targetType',\n header: t('scheduler.field.target', 'Target'),\n cell: ({ row }) => {\n const target = row.original.targetType === 'queue'\n ? row.original.targetQueue\n : row.original.targetCommand\n return (\n <div className=\"flex flex-col\">\n <span className=\"text-xs text-muted-foreground capitalize\">{row.original.targetType}</span>\n <span className=\"text-sm\">{target || '-'}</span>\n </div>\n )\n },\n },\n {\n id: 'nextRunAt',\n accessorKey: 'nextRunAt',\n header: t('scheduler.field.next_run', 'Next Run'),\n cell: ({ row }) => (\n <span className=\"text-sm\">\n {formatDateTime(row.original.nextRunAt) || '-'}\n </span>\n ),\n },\n {\n id: 'isEnabled',\n accessorKey: 'isEnabled',\n header: t('scheduler.field.active', 'Active'),\n cell: ({ row }) => <BooleanIcon value={row.original.isEnabled} />,\n },\n {\n id: 'sourceType',\n accessorKey: 'sourceType',\n header: t('scheduler.field.source', 'Source'),\n cell: ({ row }) => (\n <span className=\"text-xs capitalize\">\n {row.original.sourceType}\n {row.original.sourceModule && ` (${row.original.sourceModule})`}\n </span>\n ),\n },\n ],\n [t]\n )\n\n const rowActions = React.useCallback(\n (row: ScheduleRow): RowActionItem[] => [\n {\n id: 'view',\n label: t('scheduler.action.view', 'View Details'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}`),\n },\n {\n id: 'edit',\n label: t('scheduler.action.edit', 'Edit'),\n onSelect: () => router.push(`/backend/config/scheduled-jobs/${row.id}/edit`),\n },\n {\n id: 'trigger',\n label: t('scheduler.action.trigger', 'Run Now'),\n onSelect: () => handleTrigger(row),\n },\n {\n id: 'delete',\n label: t('scheduler.action.delete', 'Delete'),\n onSelect: () => handleDelete(row),\n destructive: true,\n },\n ],\n [t, router, handleDelete, handleTrigger]\n )\n\n return (\n <Page>\n <PageBody>\n <DataTable<ScheduleRow>\n title={t('scheduler.title', 'Scheduled Jobs')}\n actions={\n <Button onClick={() => router.push('/backend/config/scheduled-jobs/new')}>\n {t('scheduler.action.create', 'New Schedule')}\n </Button>\n }\n columns={columns}\n data={rows}\n onRowClick={(row) => router.push(`/backend/config/scheduled-jobs/${row.id}`)}\n rowActions={(row) => <RowActions items={rowActions(row)} />}\n emptyState={(\n <ListEmptyState\n entityName={t('scheduler.title', 'Scheduled Jobs')}\n createHref=\"/backend/config/scheduled-jobs/new\"\n createLabel={t('scheduler.action.create', 'New Schedule')}\n />\n )}\n pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}\n isLoading={isLoading}\n searchValue={search}\n onSearchChange={(value) => { setSearch(value); setPage(1) }}\n searchPlaceholder={t('scheduler.search.placeholder', 'Search schedules...')}\n refreshButton={{\n label: t('scheduler.action.refresh', 'Refresh'),\n onRefresh: fetchSchedules,\n }}\n />\n {ConfirmDialogElement}\n </PageBody>\n </Page>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/scheduler",
3
- "version": "0.6.5-develop.4788.1.a3e2520ec0",
3
+ "version": "0.6.5-develop.4790.1.bffb4fd44b",
4
4
  "description": "Database-managed scheduled jobs with admin UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -58,13 +58,13 @@
58
58
  "./*/*/*/*/*/*.json": "./src/*/*/*/*/*/*.json"
59
59
  },
60
60
  "dependencies": {
61
- "@open-mercato/events": "0.6.5-develop.4788.1.a3e2520ec0",
62
- "@open-mercato/queue": "0.6.5-develop.4788.1.a3e2520ec0",
61
+ "@open-mercato/events": "0.6.5-develop.4790.1.bffb4fd44b",
62
+ "@open-mercato/queue": "0.6.5-develop.4790.1.bffb4fd44b",
63
63
  "cron-parser": "^5.5.0"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "@mikro-orm/core": "^7.0.14",
67
- "@open-mercato/shared": "0.6.5-develop.4788.1.a3e2520ec0",
67
+ "@open-mercato/shared": "0.6.5-develop.4790.1.bffb4fd44b",
68
68
  "bullmq": "^5.0.0",
69
69
  "ioredis": "^5.0.0",
70
70
  "zod": ">=3.23.0"
@@ -78,7 +78,7 @@
78
78
  }
79
79
  },
80
80
  "devDependencies": {
81
- "@open-mercato/shared": "0.6.5-develop.4788.1.a3e2520ec0",
81
+ "@open-mercato/shared": "0.6.5-develop.4790.1.bffb4fd44b",
82
82
  "@types/jest": "^30.0.0",
83
83
  "@types/node": "^25.9.1",
84
84
  "jest": "^30.4.2",
@@ -14,6 +14,7 @@ import { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'
14
14
  import { useT } from '@open-mercato/shared/lib/i18n/context'
15
15
  import { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'
16
16
  import { formatDateTime } from '@open-mercato/shared/lib/time'
17
+ import { ListEmptyState } from '@open-mercato/ui/backend/filters/ListEmptyState'
17
18
 
18
19
  type ScheduleRow = {
19
20
  id: string
@@ -196,7 +197,7 @@ export default function SchedulerPage() {
196
197
  : row.original.targetCommand
197
198
  return (
198
199
  <div className="flex flex-col">
199
- <span className="text-xs text-gray-500 capitalize">{row.original.targetType}</span>
200
+ <span className="text-xs text-muted-foreground capitalize">{row.original.targetType}</span>
200
201
  <span className="text-sm">{target || '-'}</span>
201
202
  </div>
202
203
  )
@@ -274,6 +275,13 @@ export default function SchedulerPage() {
274
275
  data={rows}
275
276
  onRowClick={(row) => router.push(`/backend/config/scheduled-jobs/${row.id}`)}
276
277
  rowActions={(row) => <RowActions items={rowActions(row)} />}
278
+ emptyState={(
279
+ <ListEmptyState
280
+ entityName={t('scheduler.title', 'Scheduled Jobs')}
281
+ createHref="/backend/config/scheduled-jobs/new"
282
+ createLabel={t('scheduler.action.create', 'New Schedule')}
283
+ />
284
+ )}
277
285
  pagination={{ page, pageSize, total, totalPages, onPageChange: setPage }}
278
286
  isLoading={isLoading}
279
287
  searchValue={search}