@open-mercato/core 0.6.5-develop.5382.1.f542de69af → 0.6.6-develop.5412.1.e2a52b14f0
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.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/crmFixtures.js +4 -0
- package/dist/helpers/integration/crmFixtures.js.map +2 -2
- package/dist/modules/attachments/api/route.js +2 -0
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/lib/access.js +18 -0
- package/dist/modules/attachments/lib/access.js.map +2 -2
- package/dist/modules/auth/services/rbacService.js +3 -2
- package/dist/modules/auth/services/rbacService.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +0 -3
- package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +43 -2
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/deals/summary/route.js +402 -0
- package/dist/modules/customers/api/deals/summary/route.js.map +7 -0
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js +16 -5
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js +22 -5
- package/dist/modules/customers/backend/customers/deals/[id]/hooks/useDealData.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +12 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +221 -56
- package/dist/modules/customers/backend/customers/deals/page.js.map +3 -3
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js +1 -1
- package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
- package/dist/modules/customers/cli.js +15 -9
- package/dist/modules/customers/cli.js.map +2 -2
- package/dist/modules/customers/components/DealsKpiStrip.js +282 -0
- package/dist/modules/customers/components/DealsKpiStrip.js.map +7 -0
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +0 -1
- package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +100 -17
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +1 -2
- package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
- package/dist/modules/customers/components/kpi/PipelineStageBar.js +63 -0
- package/dist/modules/customers/components/kpi/PipelineStageBar.js.map +7 -0
- package/dist/modules/customers/lib/dealsMetrics.js +82 -0
- package/dist/modules/customers/lib/dealsMetrics.js.map +7 -0
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js +2 -1
- package/dist/modules/directory/subscribers/invalidateOrgScopeCache.js.map +2 -2
- package/dist/modules/directory/utils/organizationScope.js +59 -27
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/entities.js +7 -0
- package/dist/modules/entities/api/entities.js.map +2 -2
- package/dist/modules/entities/api/records.js +26 -15
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js +14 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js +14 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/records/create/page.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +12 -0
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/entities/components/useRecordsEntityGuard.js +30 -0
- package/dist/modules/entities/components/useRecordsEntityGuard.js.map +7 -0
- package/dist/modules/query_index/lib/engine.js +4 -2
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/staff/api/team-members.js +9 -2
- package/dist/modules/staff/api/team-members.js.map +2 -2
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js +24 -1
- package/dist/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js +11 -6
- package/dist/modules/staff/backend/staff/team-members/[id]/page.js.map +2 -2
- package/dist/modules/staff/commands/team-members.js +1 -1
- package/dist/modules/staff/commands/team-members.js.map +2 -2
- package/dist/modules/staff/components/TeamMemberForm.js +1 -1
- package/dist/modules/staff/components/TeamMemberForm.js.map +2 -2
- package/dist/modules/staff/lib/scheduleSwitch.js +23 -0
- package/dist/modules/staff/lib/scheduleSwitch.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/create/page.js +1 -2
- package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js +1 -2
- package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -2
- package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialog.js +4 -13
- package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +4 -13
- package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
- package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -4
- package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +2 -5
- package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
- package/package.json +8 -8
- package/src/helpers/integration/crmFixtures.ts +21 -1
- package/src/modules/attachments/AGENTS.md +79 -0
- package/src/modules/attachments/api/route.ts +2 -0
- package/src/modules/attachments/lib/access.ts +36 -0
- package/src/modules/auth/services/rbacService.ts +11 -2
- package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +0 -3
- package/src/modules/customers/api/deals/route.ts +51 -2
- package/src/modules/customers/api/deals/summary/route.ts +496 -0
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealActivities.ts +28 -6
- package/src/modules/customers/backend/customers/deals/[id]/hooks/useDealData.ts +33 -6
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +17 -2
- package/src/modules/customers/backend/customers/deals/page.tsx +254 -66
- package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +1 -2
- package/src/modules/customers/cli.ts +15 -15
- package/src/modules/customers/components/DealsKpiStrip.tsx +389 -0
- package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +0 -1
- package/src/modules/customers/components/detail/DealForm.tsx +121 -19
- package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +1 -2
- package/src/modules/customers/components/kpi/PipelineStageBar.tsx +77 -0
- package/src/modules/customers/i18n/de.json +43 -0
- package/src/modules/customers/i18n/en.json +43 -0
- package/src/modules/customers/i18n/es.json +43 -0
- package/src/modules/customers/i18n/pl.json +43 -0
- package/src/modules/customers/lib/dealsMetrics.ts +159 -0
- package/src/modules/directory/subscribers/invalidateOrgScopeCache.ts +3 -1
- package/src/modules/directory/utils/organizationScope.ts +85 -30
- package/src/modules/entities/api/entities.ts +11 -0
- package/src/modules/entities/api/records.ts +46 -25
- package/src/modules/entities/backend/entities/user/[entityId]/records/[recordId]/page.tsx +15 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/create/page.tsx +15 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +23 -0
- package/src/modules/entities/components/useRecordsEntityGuard.ts +41 -0
- package/src/modules/entities/i18n/de.json +1 -0
- package/src/modules/entities/i18n/en.json +1 -0
- package/src/modules/entities/i18n/es.json +1 -0
- package/src/modules/entities/i18n/pl.json +1 -0
- package/src/modules/query_index/lib/engine.ts +11 -5
- package/src/modules/staff/api/team-members.ts +9 -2
- package/src/modules/staff/api/timesheets/time-entries/[id]/timer-start/route.ts +31 -1
- package/src/modules/staff/backend/staff/team-members/[id]/page.tsx +18 -8
- package/src/modules/staff/commands/team-members.ts +5 -2
- package/src/modules/staff/components/TeamMemberForm.tsx +4 -1
- package/src/modules/staff/i18n/de.json +1 -0
- package/src/modules/staff/i18n/en.json +1 -0
- package/src/modules/staff/i18n/es.json +1 -0
- package/src/modules/staff/i18n/pl.json +1 -0
- package/src/modules/staff/lib/scheduleSwitch.ts +46 -0
- package/src/modules/workflows/backend/definitions/create/page.tsx +1 -2
- package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +1 -2
- package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -2
- package/src/modules/workflows/components/NodeEditDialog.tsx +1 -4
- package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +4 -7
- package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -2
- package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +2 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/commands/team-members.ts"],
|
|
4
|
-
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { buildCustomFieldResetMap, diffCustomFieldChanges, loadCustomFieldSnapshot, type CustomFieldSnapshot } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { StaffTeam, StaffTeamMember, StaffTeamRole } from '../data/entities'\nimport {\n staffTeamMemberCreateSchema,\n staffTeamMemberUpdateSchema,\n type StaffTeamMemberCreateInput,\n type StaffTeamMemberUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst teamMemberCrudIndexer: CrudIndexerConfig<StaffTeamMember> = {\n entityType: E.staff.staff_team_member,\n}\n\ntype TeamMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n teamId: string | null\n displayName: string\n description: string | null\n userId: string | null\n roleIds: string[]\n tags: string[]\n isActive: boolean\n deletedAt: string | null\n}\n\ntype TeamMemberUndoPayload = {\n before?: TeamMemberSnapshot | null\n after?: TeamMemberSnapshot | null\n customBefore?: CustomFieldSnapshot | null\n customAfter?: CustomFieldSnapshot | null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const set = new Set<string>()\n value.forEach((entry) => {\n if (typeof entry === 'string') {\n const trimmed = entry.trim()\n if (trimmed.length) set.add(trimmed)\n }\n })\n return Array.from(set)\n}\n\nasync function loadTeamMemberSnapshot(em: EntityManager, id: string): Promise<TeamMemberSnapshot | null> {\n const member = await findOneWithDecryption(em, StaffTeamMember, { id }, undefined, { tenantId: null, organizationId: null })\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n teamId: member.teamId ?? null,\n displayName: member.displayName,\n description: member.description ?? null,\n userId: member.userId ?? null,\n roleIds: Array.isArray(member.roleIds) ? member.roleIds : [],\n tags: Array.isArray(member.tags) ? member.tags : [],\n isActive: member.isActive ?? true,\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTeamMemberCustomSnapshot(\n em: EntityManager,\n snapshot: TeamMemberSnapshot,\n): Promise<CustomFieldSnapshot> {\n return loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member,\n recordId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n}\n\nfunction teamMemberSeedFromSnapshot(snapshot: TeamMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n teamId: snapshot.teamId ?? null,\n displayName: snapshot.displayName,\n description: snapshot.description ?? null,\n userId: snapshot.userId ?? null,\n roleIds: Array.isArray(snapshot.roleIds) ? snapshot.roleIds : [],\n tags: Array.isArray(snapshot.tags) ? snapshot.tags : [],\n availabilityRuleSetId: null,\n isActive: snapshot.isActive,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst redoTeamMemberCreate = makeCreateRedo<StaffTeamMember, TeamMemberSnapshot, StaffTeamMemberCreateInput, { memberId: string }>({\n entityClass: StaffTeamMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: teamMemberSeedFromSnapshot,\n buildResult: (entity) => ({ memberId: entity.id }),\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n})\n\nasync function ensureRolesExist(em: EntityManager, roleIds: string[], tenantId: string, organizationId: string): Promise<void> {\n if (!roleIds.length) return\n const roles = await findWithDecryption(\n em,\n StaffTeamRole,\n { id: { $in: roleIds }, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (roles.length !== roleIds.length) {\n throw new CrudHttpError(400, { error: 'One or more team roles were not found.' })\n }\n}\n\nasync function ensureUserExists(em: EntityManager, userId: string, tenantId: string, organizationId: string): Promise<void> {\n const user = await findOneWithDecryption(\n em,\n User,\n { id: userId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!user) throw new CrudHttpError(400, { error: 'User not found.' })\n if (user.tenantId && user.tenantId !== tenantId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this tenant.' })\n }\n if (user.organizationId && user.organizationId !== organizationId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this organization.' })\n }\n}\n\nasync function ensureTeamExists(em: EntityManager, teamId: string, tenantId: string, organizationId: string): Promise<void> {\n const team = await findOneWithDecryption(\n em,\n StaffTeam,\n { id: teamId, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!team) throw new CrudHttpError(400, { error: 'Team not found.' })\n}\n\nconst createTeamMemberCommand: CommandHandler<StaffTeamMemberCreateInput, { memberId: string }> = {\n id: 'staff.team-members.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roleIds = normalizeStringList(parsed.roleIds)\n const tags = normalizeStringList(parsed.tags)\n if (parsed.userId) {\n await ensureUserExists(em, parsed.userId, parsed.tenantId, parsed.organizationId)\n }\n if (parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, parsed.tenantId, parsed.organizationId)\n }\n await ensureRolesExist(em, roleIds, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const member = em.create(StaffTeamMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n teamId: parsed.teamId ?? null,\n displayName: parsed.displayName,\n description: parsed.description ?? null,\n userId: parsed.userId ?? null,\n roleIds,\n tags,\n availabilityRuleSetId: parsed.availabilityRuleSetId ?? null,\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { snapshot, custom }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.create', 'Create team member'),\n resourceKind: 'staff.teamMember',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n customAfter: custom,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: after.id })\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const result = await redoTeamMemberCreate({ input: undefined as unknown as StaffTeamMemberCreateInput, ctx, logEntry })\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const customAfter = payload?.customAfter\n if (customAfter && Object.keys(customAfter).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine') as DataEngine,\n entityId: E.staff.staff_team_member,\n recordId: result.memberId,\n tenantId: payload?.after?.tenantId ?? '',\n organizationId: payload?.after?.organizationId ?? '',\n values: customAfter,\n })\n }\n return result\n },\n}\n\nconst updateTeamMemberCommand: CommandHandler<StaffTeamMemberUpdateInput, { memberId: string }> = {\n id: 'staff.team-members.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, parsed.id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: parsed.id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n // Resolve validation queries BEFORE mutating scalars: `ensure*` runs `em.find`,\n // which would otherwise reset unit-of-work tracking between mutations and the\n // flush and silently drop earlier scalar changes (SPEC-018 Problem 1).\n if (parsed.userId !== undefined && parsed.userId) {\n await ensureUserExists(em, parsed.userId, member.tenantId, member.organizationId)\n }\n if (parsed.teamId !== undefined && parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, member.tenantId, member.organizationId)\n }\n let nextRoleIds: string[] | undefined\n if (parsed.roleIds !== undefined) {\n nextRoleIds = normalizeStringList(parsed.roleIds)\n await ensureRolesExist(em, nextRoleIds, member.tenantId, member.organizationId)\n }\n\n await withAtomicFlush(em, [\n () => {\n if (parsed.userId !== undefined) member.userId = parsed.userId ?? null\n if (parsed.teamId !== undefined) member.teamId = parsed.teamId ?? null\n if (parsed.roleIds !== undefined) member.roleIds = nextRoleIds ?? []\n if (parsed.tags !== undefined) member.tags = normalizeStringList(parsed.tags)\n if (parsed.availabilityRuleSetId !== undefined) member.availabilityRuleSetId = parsed.availabilityRuleSetId ?? null\n if (parsed.displayName !== undefined) member.displayName = parsed.displayName\n if (parsed.description !== undefined) member.description = parsed.description ?? null\n if (parsed.isActive !== undefined) member.isActive = parsed.isActive\n member.updatedAt = new Date()\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTeamMemberSnapshot(em, before.id)\n if (!after) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const customAfter = await loadTeamMemberCustomSnapshot(em, after)\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'teamId',\n 'displayName',\n 'description',\n 'userId',\n 'roleIds',\n 'tags',\n 'isActive',\n 'deletedAt',\n ])\n const customChanges = diffCustomFieldChanges(customBefore, customAfter)\n if (Object.keys(customChanges).length) {\n changes.customFields = { from: customBefore ?? null, to: customAfter ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.update', 'Update team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n customBefore: customBefore ?? null,\n customAfter,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) return\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = Array.isArray(before.roleIds) ? before.roleIds : []\n member.tags = Array.isArray(before.tags) ? before.tags : []\n member.isActive = before.isActive\n member.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore || payload.customAfter) {\n const reset = buildCustomFieldResetMap(payload.customBefore ?? undefined, payload.customAfter ?? undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nconst deleteTeamMemberCommand: CommandHandler<{ id?: string }, { memberId: string }> = {\n id: 'staff.team-members.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.delete', 'Delete team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n customBefore: customBefore ?? null,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) {\n member = em.create(StaffTeamMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n teamId: before.teamId ?? null,\n displayName: before.displayName,\n description: before.description ?? null,\n userId: before.userId ?? null,\n roleIds: before.roleIds ?? [],\n tags: before.tags ?? [],\n isActive: before.isActive,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = before.roleIds ?? []\n member.tags = before.tags ?? []\n member.isActive = before.isActive\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore) {\n const reset = buildCustomFieldResetMap(payload.customBefore, undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTeamMemberCommand)\nregisterCommand(updateTeamMemberCommand)\nregisterCommand(deleteTeamMemberCommand)\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { registerCommand } from '@open-mercato/shared/lib/commands'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { buildChanges, emitCrudSideEffects, emitCrudUndoSideEffects, parseWithCustomFields, setCustomFieldsIfAny } from '@open-mercato/shared/lib/commands/helpers'\nimport { buildCustomFieldResetMap, diffCustomFieldChanges, loadCustomFieldSnapshot, type CustomFieldSnapshot } from '@open-mercato/shared/lib/commands/customFieldSnapshots'\nimport { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'\nimport { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { CrudIndexerConfig } from '@open-mercato/shared/lib/crud/types'\nimport { User } from '@open-mercato/core/modules/auth/data/entities'\nimport { StaffTeam, StaffTeamMember, StaffTeamRole } from '../data/entities'\nimport {\n staffTeamMemberCreateSchema,\n staffTeamMemberUpdateSchema,\n type StaffTeamMemberCreateInput,\n type StaffTeamMemberUpdateInput,\n} from '../data/validators'\nimport { staffTeamMemberCrudEvents } from '../lib/crud'\nimport { ensureOrganizationScope, ensureTenantScope, extractUndoPayload } from './shared'\nimport { E } from '#generated/entities.ids.generated'\n\nconst teamMemberCrudIndexer: CrudIndexerConfig<StaffTeamMember> = {\n entityType: E.staff.staff_team_member,\n}\n\ntype TeamMemberSnapshot = {\n id: string\n tenantId: string\n organizationId: string\n teamId: string | null\n displayName: string\n description: string | null\n userId: string | null\n roleIds: string[]\n tags: string[]\n isActive: boolean\n deletedAt: string | null\n}\n\ntype TeamMemberUndoPayload = {\n before?: TeamMemberSnapshot | null\n after?: TeamMemberSnapshot | null\n customBefore?: CustomFieldSnapshot | null\n customAfter?: CustomFieldSnapshot | null\n}\n\nfunction normalizeStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return []\n const set = new Set<string>()\n value.forEach((entry) => {\n if (typeof entry === 'string') {\n const trimmed = entry.trim()\n if (trimmed.length) set.add(trimmed)\n }\n })\n return Array.from(set)\n}\n\nasync function loadTeamMemberSnapshot(em: EntityManager, id: string): Promise<TeamMemberSnapshot | null> {\n const member = await findOneWithDecryption(em, StaffTeamMember, { id }, undefined, { tenantId: null, organizationId: null })\n if (!member) return null\n return {\n id: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n teamId: member.teamId ?? null,\n displayName: member.displayName,\n description: member.description ?? null,\n userId: member.userId ?? null,\n roleIds: Array.isArray(member.roleIds) ? member.roleIds : [],\n tags: Array.isArray(member.tags) ? member.tags : [],\n isActive: member.isActive ?? true,\n deletedAt: member.deletedAt ? member.deletedAt.toISOString() : null,\n }\n}\n\nasync function loadTeamMemberCustomSnapshot(\n em: EntityManager,\n snapshot: TeamMemberSnapshot,\n): Promise<CustomFieldSnapshot> {\n return loadCustomFieldSnapshot(em, {\n entityId: E.staff.staff_team_member,\n recordId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n })\n}\n\nfunction teamMemberSeedFromSnapshot(snapshot: TeamMemberSnapshot): Record<string, unknown> {\n return {\n id: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n teamId: snapshot.teamId ?? null,\n displayName: snapshot.displayName,\n description: snapshot.description ?? null,\n userId: snapshot.userId ?? null,\n roleIds: Array.isArray(snapshot.roleIds) ? snapshot.roleIds : [],\n tags: Array.isArray(snapshot.tags) ? snapshot.tags : [],\n availabilityRuleSetId: null,\n isActive: snapshot.isActive,\n createdAt: new Date(),\n updatedAt: new Date(),\n deletedAt: null,\n }\n}\n\nconst redoTeamMemberCreate = makeCreateRedo<StaffTeamMember, TeamMemberSnapshot, StaffTeamMemberCreateInput, { memberId: string }>({\n entityClass: StaffTeamMember,\n getSnapshotId: (snapshot) => snapshot.id,\n seedFromSnapshot: teamMemberSeedFromSnapshot,\n buildResult: (entity) => ({ memberId: entity.id }),\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n})\n\nasync function ensureRolesExist(em: EntityManager, roleIds: string[], tenantId: string, organizationId: string): Promise<void> {\n if (!roleIds.length) return\n const roles = await findWithDecryption(\n em,\n StaffTeamRole,\n { id: { $in: roleIds }, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (roles.length !== roleIds.length) {\n throw new CrudHttpError(400, { error: 'One or more team roles were not found.' })\n }\n}\n\nasync function ensureUserExists(em: EntityManager, userId: string, tenantId: string, organizationId: string): Promise<void> {\n const user = await findOneWithDecryption(\n em,\n User,\n { id: userId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!user) throw new CrudHttpError(400, { error: 'User not found.' })\n if (user.tenantId && user.tenantId !== tenantId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this tenant.' })\n }\n if (user.organizationId && user.organizationId !== organizationId) {\n throw new CrudHttpError(400, { error: 'User does not belong to this organization.' })\n }\n}\n\nasync function ensureTeamExists(em: EntityManager, teamId: string, tenantId: string, organizationId: string): Promise<void> {\n const team = await findOneWithDecryption(\n em,\n StaffTeam,\n { id: teamId, tenantId, organizationId, deletedAt: null },\n undefined,\n { tenantId, organizationId },\n )\n if (!team) throw new CrudHttpError(400, { error: 'Team not found.' })\n}\n\nconst createTeamMemberCommand: CommandHandler<StaffTeamMemberCreateInput, { memberId: string }> = {\n id: 'staff.team-members.create',\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberCreateSchema, rawInput)\n ensureTenantScope(ctx, parsed.tenantId)\n ensureOrganizationScope(ctx, parsed.organizationId)\n\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const roleIds = normalizeStringList(parsed.roleIds)\n const tags = normalizeStringList(parsed.tags)\n if (parsed.userId) {\n await ensureUserExists(em, parsed.userId, parsed.tenantId, parsed.organizationId)\n }\n if (parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, parsed.tenantId, parsed.organizationId)\n }\n await ensureRolesExist(em, roleIds, parsed.tenantId, parsed.organizationId)\n\n const now = new Date()\n const member = em.create(StaffTeamMember, {\n tenantId: parsed.tenantId,\n organizationId: parsed.organizationId,\n teamId: parsed.teamId ?? null,\n displayName: parsed.displayName,\n description: parsed.description ?? null,\n userId: parsed.userId ?? null,\n roleIds,\n tags,\n availabilityRuleSetId: parsed.availabilityRuleSetId ?? null,\n isActive: parsed.isActive ?? true,\n createdAt: now,\n updatedAt: now,\n deletedAt: null,\n })\n em.persist(member)\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { snapshot, custom }\n },\n buildLog: async ({ result, ctx }) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const snapshot = await loadTeamMemberSnapshot(em, result.memberId)\n if (!snapshot) return null\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.create', 'Create team member'),\n resourceKind: 'staff.teamMember',\n resourceId: snapshot.id,\n tenantId: snapshot.tenantId,\n organizationId: snapshot.organizationId,\n snapshotAfter: snapshot,\n payload: {\n undo: {\n after: snapshot,\n customAfter: custom,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: after.id })\n if (member) {\n member.deletedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n }\n },\n redo: async ({ logEntry, ctx }) => {\n const result = await redoTeamMemberCreate({ input: undefined as unknown as StaffTeamMemberCreateInput, ctx, logEntry })\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const customAfter = payload?.customAfter\n if (customAfter && Object.keys(customAfter).length) {\n await setCustomFieldsIfAny({\n dataEngine: ctx.container.resolve('dataEngine') as DataEngine,\n entityId: E.staff.staff_team_member,\n recordId: result.memberId,\n tenantId: payload?.after?.tenantId ?? '',\n organizationId: payload?.after?.organizationId ?? '',\n values: customAfter,\n })\n }\n return result\n },\n}\n\nconst updateTeamMemberCommand: CommandHandler<StaffTeamMemberUpdateInput, { memberId: string; updatedAt: string | null }> = {\n id: 'staff.team-members.update',\n async prepare(rawInput, ctx) {\n const { parsed } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, parsed.id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(rawInput, ctx) {\n const { parsed, custom } = parseWithCustomFields(staffTeamMemberUpdateSchema, rawInput)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id: parsed.id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n\n // Resolve validation queries BEFORE mutating scalars: `ensure*` runs `em.find`,\n // which would otherwise reset unit-of-work tracking between mutations and the\n // flush and silently drop earlier scalar changes (SPEC-018 Problem 1).\n if (parsed.userId !== undefined && parsed.userId) {\n await ensureUserExists(em, parsed.userId, member.tenantId, member.organizationId)\n }\n if (parsed.teamId !== undefined && parsed.teamId) {\n await ensureTeamExists(em, parsed.teamId, member.tenantId, member.organizationId)\n }\n let nextRoleIds: string[] | undefined\n if (parsed.roleIds !== undefined) {\n nextRoleIds = normalizeStringList(parsed.roleIds)\n await ensureRolesExist(em, nextRoleIds, member.tenantId, member.organizationId)\n }\n\n await withAtomicFlush(em, [\n () => {\n if (parsed.userId !== undefined) member.userId = parsed.userId ?? null\n if (parsed.teamId !== undefined) member.teamId = parsed.teamId ?? null\n if (parsed.roleIds !== undefined) member.roleIds = nextRoleIds ?? []\n if (parsed.tags !== undefined) member.tags = normalizeStringList(parsed.tags)\n if (parsed.availabilityRuleSetId !== undefined) member.availabilityRuleSetId = parsed.availabilityRuleSetId ?? null\n if (parsed.displayName !== undefined) member.displayName = parsed.displayName\n if (parsed.description !== undefined) member.description = parsed.description ?? null\n if (parsed.isActive !== undefined) member.isActive = parsed.isActive\n member.updatedAt = new Date()\n },\n ], { transaction: true })\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: custom,\n })\n\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n // Return the freshly-bumped updatedAt so non-CrudForm callers (e.g. the\n // availability schedule switcher) can refresh their optimistic-lock token\n // and not falsely 409 on the next sequential edit (#2848).\n return { memberId: member.id, updatedAt: member.updatedAt ? member.updatedAt.toISOString() : null }\n },\n buildLog: async ({ snapshots, ctx }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const after = await loadTeamMemberSnapshot(em, before.id)\n if (!after) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const customAfter = await loadTeamMemberCustomSnapshot(em, after)\n const changes = buildChanges(before as unknown as Record<string, unknown>, after as unknown as Record<string, unknown>, [\n 'teamId',\n 'displayName',\n 'description',\n 'userId',\n 'roleIds',\n 'tags',\n 'isActive',\n 'deletedAt',\n ])\n const customChanges = diffCustomFieldChanges(customBefore, customAfter)\n if (Object.keys(customChanges).length) {\n changes.customFields = { from: customBefore ?? null, to: customAfter ?? null }\n }\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.update', 'Update team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n snapshotAfter: after,\n changes,\n payload: {\n undo: {\n before,\n after,\n customBefore: customBefore ?? null,\n customAfter,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) return\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = Array.isArray(before.roleIds) ? before.roleIds : []\n member.tags = Array.isArray(before.tags) ? before.tags : []\n member.isActive = before.isActive\n member.deletedAt = before.deletedAt ? new Date(before.deletedAt) : null\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore || payload.customAfter) {\n const reset = buildCustomFieldResetMap(payload.customBefore ?? undefined, payload.customAfter ?? undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'updated',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nconst deleteTeamMemberCommand: CommandHandler<{ id?: string }, { memberId: string }> = {\n id: 'staff.team-members.delete',\n async prepare(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager)\n const snapshot = await loadTeamMemberSnapshot(em, id)\n if (!snapshot) return {}\n const custom = await loadTeamMemberCustomSnapshot(em, snapshot)\n return { before: snapshot, customBefore: custom }\n },\n async execute(input, ctx) {\n const id = input?.id\n if (!id) throw new CrudHttpError(400, { error: 'Member id is required.' })\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const member = await findOneWithDecryption(\n em,\n StaffTeamMember,\n { id, deletedAt: null },\n undefined,\n { tenantId: ctx.auth?.tenantId ?? null, organizationId: ctx.auth?.orgId ?? null },\n )\n if (!member) throw new CrudHttpError(404, { error: 'Team member not found.' })\n ensureTenantScope(ctx, member.tenantId)\n ensureOrganizationScope(ctx, member.organizationId)\n member.deletedAt = new Date()\n member.updatedAt = new Date()\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n await emitCrudSideEffects({\n dataEngine: de,\n action: 'deleted',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n\n return { memberId: member.id }\n },\n buildLog: async ({ snapshots }) => {\n const before = snapshots.before as TeamMemberSnapshot | undefined\n if (!before) return null\n const customBefore = (snapshots as { customBefore?: CustomFieldSnapshot | null }).customBefore ?? undefined\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('staff.audit.teamMembers.delete', 'Delete team member'),\n resourceKind: 'staff.teamMember',\n resourceId: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: {\n undo: {\n before,\n customBefore: customBefore ?? null,\n } satisfies TeamMemberUndoPayload,\n },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<TeamMemberUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n let member = await em.findOne(StaffTeamMember, { id: before.id })\n if (!member) {\n member = em.create(StaffTeamMember, {\n id: before.id,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n teamId: before.teamId ?? null,\n displayName: before.displayName,\n description: before.description ?? null,\n userId: before.userId ?? null,\n roleIds: before.roleIds ?? [],\n tags: before.tags ?? [],\n isActive: before.isActive,\n deletedAt: null,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(member)\n } else {\n member.teamId = before.teamId ?? null\n member.displayName = before.displayName\n member.description = before.description ?? null\n member.userId = before.userId ?? null\n member.roleIds = before.roleIds ?? []\n member.tags = before.tags ?? []\n member.isActive = before.isActive\n member.deletedAt = null\n member.updatedAt = new Date()\n }\n await em.flush()\n\n const de = (ctx.container.resolve('dataEngine') as DataEngine)\n if (payload.customBefore) {\n const reset = buildCustomFieldResetMap(payload.customBefore, undefined)\n await setCustomFieldsIfAny({\n dataEngine: de,\n entityId: E.staff.staff_team_member,\n recordId: member.id,\n tenantId: member.tenantId,\n organizationId: member.organizationId,\n values: reset,\n })\n }\n\n await emitCrudUndoSideEffects({\n dataEngine: de,\n action: 'created',\n entity: member,\n identifiers: {\n id: member.id,\n organizationId: member.organizationId,\n tenantId: member.tenantId,\n },\n events: staffTeamMemberCrudEvents,\n indexer: teamMemberCrudIndexer,\n })\n },\n}\n\nregisterCommand(createTeamMemberCommand)\nregisterCommand(updateTeamMemberCommand)\nregisterCommand(deleteTeamMemberCommand)\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -366,7 +366,7 @@ function TeamMemberForm(props) {
|
|
|
366
366
|
if (!tagsSection) {
|
|
367
367
|
baseFields.splice(5, 0, {
|
|
368
368
|
id: "tags",
|
|
369
|
-
label:
|
|
369
|
+
label: "",
|
|
370
370
|
type: "tags",
|
|
371
371
|
placeholder: translate("staff.teamMembers.form.fields.tags.placeholder", "Add tags")
|
|
372
372
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/staff/components/TeamMemberForm.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { LookupSelect, type LookupSelectItem } from '@open-mercato/ui/backend/inputs'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { AttachmentsSection, TagsSection, type TagOption, type TagsSectionLabels } from '@open-mercato/ui/backend/detail'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Plus } from 'lucide-react'\n\nconst DEFAULT_PAGE_SIZE = 100\n\nexport type TeamMemberFormValues = {\n id?: string\n teamId?: string | null\n userId?: string | null\n displayName?: string | null\n description?: string | null\n roleIds?: string[]\n tags?: string[]\n isActive?: boolean\n updatedAt?: string | null\n} & Record<string, unknown>\n\nexport type TeamMemberFormProps = {\n title: string\n submitLabel?: string\n backHref: string\n cancelHref: string\n embedded?: boolean\n initialValues: TeamMemberFormValues\n onSubmit: (values: TeamMemberFormValues) => Promise<void>\n onDelete?: () => Promise<void>\n isLoading?: boolean\n loadingMessage?: string\n tagsSection?: TeamMemberTagsSectionConfig\n}\n\ntype TeamRoleRow = {\n id: string\n name: string\n teamId: string | null\n}\n\ntype TeamRolesResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype UsersResponse = {\n items?: Array<{ id?: string; email?: string; organizationName?: string | null }>\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\ntype TeamMemberTagsSectionConfig = {\n title: string\n tags: TagOption[]\n onChange: (next: TagOption[]) => void\n loadOptions: (query?: string) => Promise<TagOption[]>\n createTag: (label: string) => Promise<TagOption>\n onSave: (payload: { next: TagOption[]; added: TagOption[]; removed: TagOption[] }) => Promise<void>\n labels: TagsSectionLabels\n}\n\nconst normalizeCustomFieldSubmitValue = (value: unknown): unknown => {\n const normalized = normalizeCustomFieldValues({ value })\n return normalized.value\n}\n\nexport const buildTeamMemberPayload = (\n values: TeamMemberFormValues,\n options: { id?: string } = {},\n): Record<string, unknown> => {\n const roleIds = Array.isArray(values.roleIds)\n ? values.roleIds.filter((item): item is string => typeof item === 'string')\n : []\n const tags = Array.isArray(values.tags)\n ? values.tags.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)\n : null\n const customFields = collectCustomFieldValues(values, { transform: normalizeCustomFieldSubmitValue })\n return {\n ...(options.id ? { id: options.id } : {}),\n teamId: values.teamId ? String(values.teamId) : null,\n userId: values.userId ? String(values.userId) : null,\n displayName: typeof values.displayName === 'string' ? values.displayName : '',\n description: typeof values.description === 'string' && values.description.trim().length ? values.description : null,\n roleIds,\n ...(tags ? { tags } : {}),\n isActive: values.isActive ?? true,\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n}\n\nexport function TeamMemberForm(props: TeamMemberFormProps) {\n const {\n title,\n submitLabel,\n backHref,\n cancelHref,\n embedded = false,\n initialValues,\n onSubmit,\n onDelete,\n isLoading,\n loadingMessage,\n tagsSection,\n } = props\n const translate = useT()\n const recordId = typeof initialValues?.id === 'string' ? initialValues.id : null\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [roles, setRoles] = React.useState<TeamRoleRow[]>([])\n const [selectedTeamId, setSelectedTeamId] = React.useState<string | null>(null)\n const [userOptions, setUserOptions] = React.useState<LookupSelectItem[]>([])\n const [teamOptions, setTeamOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [roleSearch, setRoleSearch] = React.useState('')\n\n const resolvedTeamId = typeof initialValues.teamId === 'string' && initialValues.teamId.trim().length\n ? initialValues.teamId\n : null\n const resolvedUserId = typeof initialValues.userId === 'string' && initialValues.userId.trim().length\n ? initialValues.userId\n : null\n\n React.useEffect(() => {\n setSelectedTeamId(resolvedTeamId)\n }, [resolvedTeamId])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRoles() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: String(DEFAULT_PAGE_SIZE) })\n const call = await apiCall<TeamRolesResponse>(`/api/staff/team-roles?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const nextRoles = items\n .map(mapTeamRole)\n .filter((role): role is TeamRoleRow => role !== null)\n if (!cancelled) setRoles(nextRoles)\n } catch {\n if (!cancelled) setRoles([])\n }\n }\n loadRoles()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadTeams() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) setTeamOptions(options)\n } catch {\n if (!cancelled) setTeamOptions([])\n }\n }\n loadTeams()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n React.useEffect(() => {\n if (!resolvedTeamId) return\n if (teamOptions.some((option) => option.value === resolvedTeamId)) return\n const selectedTeamId = resolvedTeamId\n let cancelled = false\n async function loadSelectedTeam() {\n try {\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?ids=${encodeURIComponent(selectedTeamId)}&pageSize=1`)\n const entry = Array.isArray(call.result?.items) ? call.result.items[0] : null\n const entryId = typeof entry?.id === 'string' ? entry.id : null\n const entryName = typeof entry?.name === 'string' ? entry.name : null\n if (!entryId || !entryName) return\n if (!cancelled) {\n setTeamOptions((prev) => {\n if (prev.some((option) => option.value === entryId)) return prev\n return [{ value: entryId, label: entryName }, ...prev]\n })\n }\n } catch {\n if (!cancelled) setTeamOptions((prev) => prev)\n }\n }\n loadSelectedTeam()\n return () => { cancelled = true }\n }, [resolvedTeamId, teamOptions])\n\n React.useEffect(() => {\n if (!resolvedUserId) return\n const userId = resolvedUserId\n if (userOptions.some((option) => option.id === resolvedUserId)) return\n let cancelled = false\n async function loadSelectedUser() {\n try {\n const call = await apiCall<UsersResponse>(`/api/auth/users?id=${encodeURIComponent(userId)}`)\n const entry = Array.isArray(call.result?.items) ? call.result.items[0] : null\n const entryId = typeof entry?.id === 'string' ? entry.id : null\n const entryEmail = typeof entry?.email === 'string' ? entry.email : null\n if (!entryId || !entryEmail) return\n if (!cancelled) {\n setUserOptions((prev) => {\n if (prev.some((option) => option.id === entryId)) return prev\n return [{ id: entryId, title: entryEmail, subtitle: entry?.organizationName ?? null }, ...prev]\n })\n }\n } catch {\n if (!cancelled) setUserOptions((prev) => prev)\n }\n }\n loadSelectedUser()\n return () => { cancelled = true }\n }, [resolvedUserId, userOptions])\n\n const filteredRoles = React.useMemo(\n () => filterRolesByTeam(roles, selectedTeamId),\n [roles, selectedTeamId],\n )\n const roleOptions = React.useMemo(\n () => filteredRoles.map((role) => ({ value: role.id, label: role.name })),\n [filteredRoles],\n )\n const filteredRoleOptions = React.useMemo(() => {\n const query = roleSearch.trim().toLowerCase()\n if (!query) return roleOptions\n return roleOptions.filter((option) => (\n option.label.toLowerCase().includes(query) || option.value.toLowerCase().includes(query)\n ))\n }, [roleOptions, roleSearch])\n const createRoleHref = React.useMemo(() => {\n const params = new URLSearchParams()\n if (selectedTeamId) params.set('teamId', selectedTeamId)\n const query = params.toString()\n return `/backend/staff/team-roles/create${query ? `?${query}` : ''}`\n }, [selectedTeamId])\n const createTeamHref = '/backend/staff/teams/create'\n\n React.useEffect(() => {\n setRoleSearch('')\n }, [selectedTeamId])\n\n const fetchUserOptions = React.useCallback(async (query?: string): Promise<LookupSelectItem[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim().length) params.set('search', query.trim())\n const call = await apiCall<UsersResponse>(`/api/auth/users?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\n .map((user): LookupSelectItem | null => {\n const id = typeof user?.id === 'string' ? user.id : null\n const email = typeof user?.email === 'string' ? user.email : null\n if (!id || !email) return null\n return {\n id,\n title: email,\n subtitle: user.organizationName ?? null,\n }\n })\n .filter((option): option is LookupSelectItem => option !== null)\n setUserOptions(options)\n return options\n }, [])\n\n const fields = React.useMemo<CrudField[]>(() => {\n const baseFields: CrudField[] = [\n {\n id: 'userId',\n label: translate('staff.teamMembers.form.fields.user', 'User'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <LookupSelect\n value={typeof value === 'string' ? value : null}\n onChange={(next) => setValue(next)}\n options={userOptions}\n fetchOptions={fetchUserOptions}\n placeholder={translate('staff.teamMembers.form.fields.user.placeholder', 'Select a user')}\n searchPlaceholder={translate('staff.teamMembers.form.fields.user.search', 'Search users')}\n emptyLabel={translate('staff.teamMembers.form.fields.user.empty', 'No users found')}\n selectedHintLabel={(id) => translate('staff.teamMembers.form.fields.user.selected', 'Selected user: {{id}}', { id })}\n />\n ),\n },\n {\n id: 'teamId',\n label: '',\n type: 'custom',\n component: ({ value, setValue, setFormValue, values, disabled }) => {\n const currentValue = typeof value === 'string' ? value : ''\n const selectedOption = teamOptions.find((option) => option.value === currentValue)\n const optionsKey = teamOptions.map((option) => `${option.value}:${option.label}`).join('\\0')\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium\">\n {translate('staff.teamMembers.form.fields.team', 'Team')}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => router.push(createTeamHref)}\n disabled={disabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('staff.teamMembers.form.actions.createTeam', 'Create new team')}\n </Button>\n </div>\n <Select\n key={`team:${currentValue}:${optionsKey}`}\n value={currentValue}\n onValueChange={(value) => {\n const nextValue = value || undefined\n const nextTeamId = value || null\n setValue(nextValue)\n setSelectedTeamId(nextTeamId)\n if (!setFormValue) return\n const roleIds = Array.isArray(values?.roleIds)\n ? values?.roleIds.filter((item): item is string => typeof item === 'string')\n : []\n const allowedRoleIds = buildAllowedRoleIdSet(roles, nextTeamId)\n const nextRoleIds = roleIds.filter((roleId) => allowedRoleIds.has(roleId))\n if (nextRoleIds.length !== roleIds.length) {\n setFormValue('roleIds', nextRoleIds)\n }\n }}\n disabled={disabled}\n >\n <SelectTrigger data-crud-focus-target=\"\">\n <SelectValue placeholder={translate('ui.forms.select.emptyOption', '\u2014')}>\n {selectedOption?.label}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n {teamOptions.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )\n },\n },\n {\n id: 'displayName',\n label: translate('staff.teamMembers.form.fields.displayName', 'Display name'),\n type: 'text',\n required: true,\n },\n {\n id: 'description',\n label: translate('staff.teamMembers.form.fields.description', 'Description'),\n type: 'richtext',\n editor: 'uiw',\n },\n {\n id: 'roleIds',\n label: '',\n type: 'custom',\n component: ({ value, setValue, disabled }) => {\n const selectedValues = Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : []\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium\">\n {translate('staff.teamMembers.form.fields.roles', 'Roles')}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => router.push(createRoleHref)}\n disabled={disabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('staff.teamMembers.form.actions.defineRole', 'Define new role')}\n </Button>\n </div>\n <input\n className=\"w-full h-8 rounded border px-2 text-sm\"\n placeholder={translate('ui.forms.listbox.searchPlaceholder', 'Search...')}\n value={roleSearch}\n onChange={(event) => setRoleSearch(event.target.value)}\n data-crud-focus-target=\"\"\n disabled={disabled}\n />\n <div className=\"rounded border max-h-48 overflow-auto divide-y\">\n {filteredRoleOptions.map((option) => {\n const isSelected = selectedValues.includes(option.value)\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => {\n const next = new Set(selectedValues)\n if (isSelected) {\n next.delete(option.value)\n } else {\n next.add(option.value)\n }\n setValue(Array.from(next))\n }}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-muted ${isSelected ? 'bg-muted' : ''}`}\n disabled={disabled}\n >\n <span className=\"inline-flex items-center gap-2\">\n <input type=\"checkbox\" className=\"size-4\" readOnly checked={isSelected} />\n <span>{option.label}</span>\n </span>\n </button>\n )\n })}\n {!filteredRoleOptions.length ? (\n <div className=\"px-3 py-2 text-sm text-muted-foreground\">\n {translate('ui.forms.listbox.noMatches', 'No matches')}\n </div>\n ) : null}\n </div>\n </div>\n )\n },\n },\n {\n id: 'isActive',\n label: translate('staff.teamMembers.form.fields.active', 'Active'),\n type: 'checkbox',\n },\n ]\n\n if (!tagsSection) {\n baseFields.splice(5, 0, {\n id: 'tags',\n label: translate('staff.teamMembers.form.fields.tags', 'Tags'),\n type: 'tags',\n placeholder: translate('staff.teamMembers.form.fields.tags.placeholder', 'Add tags'),\n })\n }\n\n return baseFields\n }, [\n createRoleHref,\n fetchUserOptions,\n filteredRoleOptions,\n roleSearch,\n roles,\n router,\n tagsSection,\n translate,\n teamOptions,\n userOptions,\n ])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'details',\n column: 1,\n fields: ['userId', 'teamId', 'displayName', 'description', 'roleIds', 'isActive'],\n },\n {\n id: 'custom',\n title: translate('entities.customFields.title', 'Custom Attributes'),\n column: 2,\n kind: 'customFields',\n },\n ]\n\n if (tagsSection) {\n baseGroups.push({\n id: 'tags',\n column: 2,\n bare: true,\n component: () => (\n <TagsSection\n title={tagsSection.title}\n tags={tagsSection.tags}\n onChange={tagsSection.onChange}\n loadOptions={tagsSection.loadOptions}\n createTag={tagsSection.createTag}\n onSave={tagsSection.onSave}\n labels={tagsSection.labels}\n />\n ),\n })\n } else {\n baseGroups.splice(1, 0, {\n id: 'tags',\n title: translate('staff.teamMembers.form.fields.tags', 'Tags'),\n column: 2,\n fields: ['tags'],\n })\n }\n\n baseGroups.push({\n id: 'attachments',\n title: translate('attachments.library.title', 'Attachments'),\n column: 1,\n component: () => (\n <AttachmentsSection\n entityId={E.staff.staff_team_member}\n recordId={recordId}\n showHeader={false}\n />\n ),\n })\n\n return baseGroups\n }, [recordId, tagsSection, translate])\n\n return (\n <CrudForm<TeamMemberFormValues>\n embedded={embedded}\n title={title}\n backHref={backHref}\n cancelHref={cancelHref}\n versionHistory={initialValues.id\n ? { resourceKind: 'staff.teamMember', resourceId: String(initialValues.id) }\n : undefined}\n submitLabel={submitLabel}\n fields={fields}\n groups={groups}\n entityId={E.staff.staff_team_member}\n initialValues={initialValues}\n optimisticLockUpdatedAt={initialValues.updatedAt}\n onSubmit={onSubmit}\n onDelete={onDelete}\n isLoading={isLoading}\n loadingMessage={loadingMessage}\n />\n )\n}\n\nfunction mapTeamRole(item: Record<string, unknown>): TeamRoleRow | null {\n const id = typeof item.id === 'string' ? item.id : ''\n if (!id) return null\n const name = typeof item.name === 'string' && item.name.trim().length ? item.name.trim() : id\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n return { id, name, teamId }\n}\n\nfunction filterRolesByTeam(roles: TeamRoleRow[], teamId: string | null): TeamRoleRow[] {\n if (!teamId) return roles.filter((role) => role.teamId == null)\n return roles.filter((role) => role.teamId == null || role.teamId === teamId)\n}\n\nfunction buildAllowedRoleIdSet(roles: TeamRoleRow[], teamId: string | null): Set<string> {\n return new Set(filterRolesByTeam(roles, teamId).map((role) => role.id))\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { useRouter } from 'next/navigation'\nimport { CrudForm, type CrudField, type CrudFormGroup } from '@open-mercato/ui/backend/CrudForm'\nimport { collectCustomFieldValues } from '@open-mercato/ui/backend/utils/customFieldValues'\nimport { normalizeCustomFieldValues } from '@open-mercato/shared/lib/custom-fields/normalize'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { LookupSelect, type LookupSelectItem } from '@open-mercato/ui/backend/inputs'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { AttachmentsSection, TagsSection, type TagOption, type TagsSectionLabels } from '@open-mercato/ui/backend/detail'\nimport { E } from '#generated/entities.ids.generated'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { Plus } from 'lucide-react'\n\nconst DEFAULT_PAGE_SIZE = 100\n\nexport type TeamMemberFormValues = {\n id?: string\n teamId?: string | null\n userId?: string | null\n displayName?: string | null\n description?: string | null\n roleIds?: string[]\n tags?: string[]\n isActive?: boolean\n updatedAt?: string | null\n} & Record<string, unknown>\n\nexport type TeamMemberFormProps = {\n title: string\n submitLabel?: string\n backHref: string\n cancelHref: string\n embedded?: boolean\n initialValues: TeamMemberFormValues\n onSubmit: (values: TeamMemberFormValues) => Promise<void>\n onDelete?: () => Promise<void>\n isLoading?: boolean\n loadingMessage?: string\n tagsSection?: TeamMemberTagsSectionConfig\n}\n\ntype TeamRoleRow = {\n id: string\n name: string\n teamId: string | null\n}\n\ntype TeamRolesResponse = {\n items?: Array<Record<string, unknown>>\n}\n\ntype UsersResponse = {\n items?: Array<{ id?: string; email?: string; organizationName?: string | null }>\n}\n\ntype TeamsResponse = {\n items?: Array<{ id?: string; name?: string }>\n}\n\ntype TeamMemberTagsSectionConfig = {\n title: string\n tags: TagOption[]\n onChange: (next: TagOption[]) => void\n loadOptions: (query?: string) => Promise<TagOption[]>\n createTag: (label: string) => Promise<TagOption>\n onSave: (payload: { next: TagOption[]; added: TagOption[]; removed: TagOption[] }) => Promise<void>\n labels: TagsSectionLabels\n}\n\nconst normalizeCustomFieldSubmitValue = (value: unknown): unknown => {\n const normalized = normalizeCustomFieldValues({ value })\n return normalized.value\n}\n\nexport const buildTeamMemberPayload = (\n values: TeamMemberFormValues,\n options: { id?: string } = {},\n): Record<string, unknown> => {\n const roleIds = Array.isArray(values.roleIds)\n ? values.roleIds.filter((item): item is string => typeof item === 'string')\n : []\n const tags = Array.isArray(values.tags)\n ? values.tags.filter((item): item is string => typeof item === 'string' && item.trim().length > 0)\n : null\n const customFields = collectCustomFieldValues(values, { transform: normalizeCustomFieldSubmitValue })\n return {\n ...(options.id ? { id: options.id } : {}),\n teamId: values.teamId ? String(values.teamId) : null,\n userId: values.userId ? String(values.userId) : null,\n displayName: typeof values.displayName === 'string' ? values.displayName : '',\n description: typeof values.description === 'string' && values.description.trim().length ? values.description : null,\n roleIds,\n ...(tags ? { tags } : {}),\n isActive: values.isActive ?? true,\n ...(Object.keys(customFields).length ? { customFields } : {}),\n }\n}\n\nexport function TeamMemberForm(props: TeamMemberFormProps) {\n const {\n title,\n submitLabel,\n backHref,\n cancelHref,\n embedded = false,\n initialValues,\n onSubmit,\n onDelete,\n isLoading,\n loadingMessage,\n tagsSection,\n } = props\n const translate = useT()\n const recordId = typeof initialValues?.id === 'string' ? initialValues.id : null\n const router = useRouter()\n const scopeVersion = useOrganizationScopeVersion()\n const [roles, setRoles] = React.useState<TeamRoleRow[]>([])\n const [selectedTeamId, setSelectedTeamId] = React.useState<string | null>(null)\n const [userOptions, setUserOptions] = React.useState<LookupSelectItem[]>([])\n const [teamOptions, setTeamOptions] = React.useState<Array<{ value: string; label: string }>>([])\n const [roleSearch, setRoleSearch] = React.useState('')\n\n const resolvedTeamId = typeof initialValues.teamId === 'string' && initialValues.teamId.trim().length\n ? initialValues.teamId\n : null\n const resolvedUserId = typeof initialValues.userId === 'string' && initialValues.userId.trim().length\n ? initialValues.userId\n : null\n\n React.useEffect(() => {\n setSelectedTeamId(resolvedTeamId)\n }, [resolvedTeamId])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadRoles() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: String(DEFAULT_PAGE_SIZE) })\n const call = await apiCall<TeamRolesResponse>(`/api/staff/team-roles?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const nextRoles = items\n .map(mapTeamRole)\n .filter((role): role is TeamRoleRow => role !== null)\n if (!cancelled) setRoles(nextRoles)\n } catch {\n if (!cancelled) setRoles([])\n }\n }\n loadRoles()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n React.useEffect(() => {\n let cancelled = false\n async function loadTeams() {\n try {\n const params = new URLSearchParams({ page: '1', pageSize: '100' })\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\n .map((team) => {\n const id = typeof team.id === 'string' ? team.id : null\n const name = typeof team.name === 'string' ? team.name : null\n if (!id || !name) return null\n return { value: id, label: name }\n })\n .filter((entry): entry is { value: string; label: string } => entry !== null)\n if (!cancelled) setTeamOptions(options)\n } catch {\n if (!cancelled) setTeamOptions([])\n }\n }\n loadTeams()\n return () => { cancelled = true }\n }, [scopeVersion])\n\n React.useEffect(() => {\n if (!resolvedTeamId) return\n if (teamOptions.some((option) => option.value === resolvedTeamId)) return\n const selectedTeamId = resolvedTeamId\n let cancelled = false\n async function loadSelectedTeam() {\n try {\n const call = await apiCall<TeamsResponse>(`/api/staff/teams?ids=${encodeURIComponent(selectedTeamId)}&pageSize=1`)\n const entry = Array.isArray(call.result?.items) ? call.result.items[0] : null\n const entryId = typeof entry?.id === 'string' ? entry.id : null\n const entryName = typeof entry?.name === 'string' ? entry.name : null\n if (!entryId || !entryName) return\n if (!cancelled) {\n setTeamOptions((prev) => {\n if (prev.some((option) => option.value === entryId)) return prev\n return [{ value: entryId, label: entryName }, ...prev]\n })\n }\n } catch {\n if (!cancelled) setTeamOptions((prev) => prev)\n }\n }\n loadSelectedTeam()\n return () => { cancelled = true }\n }, [resolvedTeamId, teamOptions])\n\n React.useEffect(() => {\n if (!resolvedUserId) return\n const userId = resolvedUserId\n if (userOptions.some((option) => option.id === resolvedUserId)) return\n let cancelled = false\n async function loadSelectedUser() {\n try {\n const call = await apiCall<UsersResponse>(`/api/auth/users?id=${encodeURIComponent(userId)}`)\n const entry = Array.isArray(call.result?.items) ? call.result.items[0] : null\n const entryId = typeof entry?.id === 'string' ? entry.id : null\n const entryEmail = typeof entry?.email === 'string' ? entry.email : null\n if (!entryId || !entryEmail) return\n if (!cancelled) {\n setUserOptions((prev) => {\n if (prev.some((option) => option.id === entryId)) return prev\n return [{ id: entryId, title: entryEmail, subtitle: entry?.organizationName ?? null }, ...prev]\n })\n }\n } catch {\n if (!cancelled) setUserOptions((prev) => prev)\n }\n }\n loadSelectedUser()\n return () => { cancelled = true }\n }, [resolvedUserId, userOptions])\n\n const filteredRoles = React.useMemo(\n () => filterRolesByTeam(roles, selectedTeamId),\n [roles, selectedTeamId],\n )\n const roleOptions = React.useMemo(\n () => filteredRoles.map((role) => ({ value: role.id, label: role.name })),\n [filteredRoles],\n )\n const filteredRoleOptions = React.useMemo(() => {\n const query = roleSearch.trim().toLowerCase()\n if (!query) return roleOptions\n return roleOptions.filter((option) => (\n option.label.toLowerCase().includes(query) || option.value.toLowerCase().includes(query)\n ))\n }, [roleOptions, roleSearch])\n const createRoleHref = React.useMemo(() => {\n const params = new URLSearchParams()\n if (selectedTeamId) params.set('teamId', selectedTeamId)\n const query = params.toString()\n return `/backend/staff/team-roles/create${query ? `?${query}` : ''}`\n }, [selectedTeamId])\n const createTeamHref = '/backend/staff/teams/create'\n\n React.useEffect(() => {\n setRoleSearch('')\n }, [selectedTeamId])\n\n const fetchUserOptions = React.useCallback(async (query?: string): Promise<LookupSelectItem[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '50' })\n if (query && query.trim().length) params.set('search', query.trim())\n const call = await apiCall<UsersResponse>(`/api/auth/users?${params.toString()}`)\n const items = Array.isArray(call.result?.items) ? call.result.items : []\n const options = items\n .map((user): LookupSelectItem | null => {\n const id = typeof user?.id === 'string' ? user.id : null\n const email = typeof user?.email === 'string' ? user.email : null\n if (!id || !email) return null\n return {\n id,\n title: email,\n subtitle: user.organizationName ?? null,\n }\n })\n .filter((option): option is LookupSelectItem => option !== null)\n setUserOptions(options)\n return options\n }, [])\n\n const fields = React.useMemo<CrudField[]>(() => {\n const baseFields: CrudField[] = [\n {\n id: 'userId',\n label: translate('staff.teamMembers.form.fields.user', 'User'),\n type: 'custom',\n component: ({ value, setValue }) => (\n <LookupSelect\n value={typeof value === 'string' ? value : null}\n onChange={(next) => setValue(next)}\n options={userOptions}\n fetchOptions={fetchUserOptions}\n placeholder={translate('staff.teamMembers.form.fields.user.placeholder', 'Select a user')}\n searchPlaceholder={translate('staff.teamMembers.form.fields.user.search', 'Search users')}\n emptyLabel={translate('staff.teamMembers.form.fields.user.empty', 'No users found')}\n selectedHintLabel={(id) => translate('staff.teamMembers.form.fields.user.selected', 'Selected user: {{id}}', { id })}\n />\n ),\n },\n {\n id: 'teamId',\n label: '',\n type: 'custom',\n component: ({ value, setValue, setFormValue, values, disabled }) => {\n const currentValue = typeof value === 'string' ? value : ''\n const selectedOption = teamOptions.find((option) => option.value === currentValue)\n const optionsKey = teamOptions.map((option) => `${option.value}:${option.label}`).join('\\0')\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium\">\n {translate('staff.teamMembers.form.fields.team', 'Team')}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => router.push(createTeamHref)}\n disabled={disabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('staff.teamMembers.form.actions.createTeam', 'Create new team')}\n </Button>\n </div>\n <Select\n key={`team:${currentValue}:${optionsKey}`}\n value={currentValue}\n onValueChange={(value) => {\n const nextValue = value || undefined\n const nextTeamId = value || null\n setValue(nextValue)\n setSelectedTeamId(nextTeamId)\n if (!setFormValue) return\n const roleIds = Array.isArray(values?.roleIds)\n ? values?.roleIds.filter((item): item is string => typeof item === 'string')\n : []\n const allowedRoleIds = buildAllowedRoleIdSet(roles, nextTeamId)\n const nextRoleIds = roleIds.filter((roleId) => allowedRoleIds.has(roleId))\n if (nextRoleIds.length !== roleIds.length) {\n setFormValue('roleIds', nextRoleIds)\n }\n }}\n disabled={disabled}\n >\n <SelectTrigger data-crud-focus-target=\"\">\n <SelectValue placeholder={translate('ui.forms.select.emptyOption', '\u2014')}>\n {selectedOption?.label}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n {teamOptions.map((option) => (\n <SelectItem key={option.value} value={option.value}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )\n },\n },\n {\n id: 'displayName',\n label: translate('staff.teamMembers.form.fields.displayName', 'Display name'),\n type: 'text',\n required: true,\n },\n {\n id: 'description',\n label: translate('staff.teamMembers.form.fields.description', 'Description'),\n type: 'richtext',\n editor: 'uiw',\n },\n {\n id: 'roleIds',\n label: '',\n type: 'custom',\n component: ({ value, setValue, disabled }) => {\n const selectedValues = Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : []\n return (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-sm font-medium\">\n {translate('staff.teamMembers.form.fields.roles', 'Roles')}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => router.push(createRoleHref)}\n disabled={disabled}\n >\n <Plus className=\"mr-2 h-4 w-4\" aria-hidden />\n {translate('staff.teamMembers.form.actions.defineRole', 'Define new role')}\n </Button>\n </div>\n <input\n className=\"w-full h-8 rounded border px-2 text-sm\"\n placeholder={translate('ui.forms.listbox.searchPlaceholder', 'Search...')}\n value={roleSearch}\n onChange={(event) => setRoleSearch(event.target.value)}\n data-crud-focus-target=\"\"\n disabled={disabled}\n />\n <div className=\"rounded border max-h-48 overflow-auto divide-y\">\n {filteredRoleOptions.map((option) => {\n const isSelected = selectedValues.includes(option.value)\n return (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => {\n const next = new Set(selectedValues)\n if (isSelected) {\n next.delete(option.value)\n } else {\n next.add(option.value)\n }\n setValue(Array.from(next))\n }}\n className={`w-full text-left px-3 py-2 text-sm hover:bg-muted ${isSelected ? 'bg-muted' : ''}`}\n disabled={disabled}\n >\n <span className=\"inline-flex items-center gap-2\">\n <input type=\"checkbox\" className=\"size-4\" readOnly checked={isSelected} />\n <span>{option.label}</span>\n </span>\n </button>\n )\n })}\n {!filteredRoleOptions.length ? (\n <div className=\"px-3 py-2 text-sm text-muted-foreground\">\n {translate('ui.forms.listbox.noMatches', 'No matches')}\n </div>\n ) : null}\n </div>\n </div>\n )\n },\n },\n {\n id: 'isActive',\n label: translate('staff.teamMembers.form.fields.active', 'Active'),\n type: 'checkbox',\n },\n ]\n\n if (!tagsSection) {\n // The tags field lives in its own card whose group title already reads\n // \"Tags\" (see groups below). Leave the field label empty so the heading\n // is not rendered twice in the team member edit view.\n baseFields.splice(5, 0, {\n id: 'tags',\n label: '',\n type: 'tags',\n placeholder: translate('staff.teamMembers.form.fields.tags.placeholder', 'Add tags'),\n })\n }\n\n return baseFields\n }, [\n createRoleHref,\n fetchUserOptions,\n filteredRoleOptions,\n roleSearch,\n roles,\n router,\n tagsSection,\n translate,\n teamOptions,\n userOptions,\n ])\n\n const groups = React.useMemo<CrudFormGroup[]>(() => {\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'details',\n column: 1,\n fields: ['userId', 'teamId', 'displayName', 'description', 'roleIds', 'isActive'],\n },\n {\n id: 'custom',\n title: translate('entities.customFields.title', 'Custom Attributes'),\n column: 2,\n kind: 'customFields',\n },\n ]\n\n if (tagsSection) {\n baseGroups.push({\n id: 'tags',\n column: 2,\n bare: true,\n component: () => (\n <TagsSection\n title={tagsSection.title}\n tags={tagsSection.tags}\n onChange={tagsSection.onChange}\n loadOptions={tagsSection.loadOptions}\n createTag={tagsSection.createTag}\n onSave={tagsSection.onSave}\n labels={tagsSection.labels}\n />\n ),\n })\n } else {\n baseGroups.splice(1, 0, {\n id: 'tags',\n title: translate('staff.teamMembers.form.fields.tags', 'Tags'),\n column: 2,\n fields: ['tags'],\n })\n }\n\n baseGroups.push({\n id: 'attachments',\n title: translate('attachments.library.title', 'Attachments'),\n column: 1,\n component: () => (\n <AttachmentsSection\n entityId={E.staff.staff_team_member}\n recordId={recordId}\n showHeader={false}\n />\n ),\n })\n\n return baseGroups\n }, [recordId, tagsSection, translate])\n\n return (\n <CrudForm<TeamMemberFormValues>\n embedded={embedded}\n title={title}\n backHref={backHref}\n cancelHref={cancelHref}\n versionHistory={initialValues.id\n ? { resourceKind: 'staff.teamMember', resourceId: String(initialValues.id) }\n : undefined}\n submitLabel={submitLabel}\n fields={fields}\n groups={groups}\n entityId={E.staff.staff_team_member}\n initialValues={initialValues}\n optimisticLockUpdatedAt={initialValues.updatedAt}\n onSubmit={onSubmit}\n onDelete={onDelete}\n isLoading={isLoading}\n loadingMessage={loadingMessage}\n />\n )\n}\n\nfunction mapTeamRole(item: Record<string, unknown>): TeamRoleRow | null {\n const id = typeof item.id === 'string' ? item.id : ''\n if (!id) return null\n const name = typeof item.name === 'string' && item.name.trim().length ? item.name.trim() : id\n const teamId = typeof item.teamId === 'string'\n ? item.teamId\n : typeof item.team_id === 'string'\n ? item.team_id\n : null\n return { id, name, teamId }\n}\n\nfunction filterRolesByTeam(roles: TeamRoleRow[], teamId: string | null): TeamRoleRow[] {\n if (!teamId) return roles.filter((role) => role.teamId == null)\n return roles.filter((role) => role.teamId == null || role.teamId === teamId)\n}\n\nfunction buildAllowedRoleIdSet(roles: TeamRoleRow[], teamId: string | null): Set<string> {\n return new Set(filterRolesByTeam(roles, teamId).map((role) => role.id))\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["selectedTeamId", "value"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { withScopedApiRequestHeaders } from "@open-mercato/ui/backend/utils/apiCall";
|
|
2
|
+
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
|
|
3
|
+
import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
|
|
4
|
+
import { updateCrud } from "@open-mercato/ui/backend/utils/crud";
|
|
5
|
+
async function switchTeamMemberSchedule(args) {
|
|
6
|
+
const { memberId, nextRuleSetId, expectedUpdatedAt, t } = args;
|
|
7
|
+
const headers = buildOptimisticLockHeader(expectedUpdatedAt);
|
|
8
|
+
try {
|
|
9
|
+
const call = await withScopedApiRequestHeaders(headers, () => updateCrud(
|
|
10
|
+
"staff/team-members",
|
|
11
|
+
{ id: memberId, availabilityRuleSetId: nextRuleSetId },
|
|
12
|
+
{ errorMessage: t("staff.teamMembers.availability.ruleset.updateError", "Failed to update schedule.") }
|
|
13
|
+
));
|
|
14
|
+
return { updatedAt: call?.result?.updatedAt ?? null };
|
|
15
|
+
} catch (error) {
|
|
16
|
+
surfaceRecordConflict(error, t);
|
|
17
|
+
throw error;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
switchTeamMemberSchedule
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=scheduleSwitch.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/staff/lib/scheduleSwitch.ts"],
|
|
4
|
+
"sourcesContent": ["import { withScopedApiRequestHeaders } from '@open-mercato/ui/backend/utils/apiCall'\nimport { buildOptimisticLockHeader } from '@open-mercato/ui/backend/utils/optimisticLock'\nimport { surfaceRecordConflict } from '@open-mercato/ui/backend/conflicts'\nimport { updateCrud } from '@open-mercato/ui/backend/utils/crud'\n\ntype Translate = (key: string, fallback?: string) => string\n\nexport type TeamMemberScheduleSwitchResult = {\n /** The team member's freshly-bumped updatedAt, used to refresh the optimistic-lock token. */\n updatedAt: string | null\n}\n\n/**\n * Persist a team member's selected availability schedule.\n *\n * Sends the optimistic-lock header derived from the caller's current\n * `expectedUpdatedAt` and returns the server's freshly-bumped `updatedAt` so the\n * caller can advance its token before the next sequential switch \u2014 otherwise the\n * second switch reuses a stale version and falsely 409s (#2848).\n *\n * On an optimistic-lock conflict the shared conflict bar is surfaced before the\n * error is re-thrown, so the selection reverts AND the user sees visible feedback\n * instead of a silent revert.\n */\nexport async function switchTeamMemberSchedule(args: {\n memberId: string\n nextRuleSetId: string | null\n expectedUpdatedAt: string | null | undefined\n t: Translate\n}): Promise<TeamMemberScheduleSwitchResult> {\n const { memberId, nextRuleSetId, expectedUpdatedAt, t } = args\n const headers = buildOptimisticLockHeader(expectedUpdatedAt)\n try {\n const call = await withScopedApiRequestHeaders(headers, () => (\n updateCrud<{ ok?: boolean; updatedAt?: string | null }>(\n 'staff/team-members',\n { id: memberId, availabilityRuleSetId: nextRuleSetId },\n { errorMessage: t('staff.teamMembers.availability.ruleset.updateError', 'Failed to update schedule.') },\n )\n ))\n return { updatedAt: call?.result?.updatedAt ?? null }\n } catch (error) {\n surfaceRecordConflict(error, t)\n throw error\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,mCAAmC;AAC5C,SAAS,iCAAiC;AAC1C,SAAS,6BAA6B;AACtC,SAAS,kBAAkB;AAqB3B,eAAsB,yBAAyB,MAKH;AAC1C,QAAM,EAAE,UAAU,eAAe,mBAAmB,EAAE,IAAI;AAC1D,QAAM,UAAU,0BAA0B,iBAAiB;AAC3D,MAAI;AACF,UAAM,OAAO,MAAM,4BAA4B,SAAS,MACtD;AAAA,MACE;AAAA,MACA,EAAE,IAAI,UAAU,uBAAuB,cAAc;AAAA,MACrD,EAAE,cAAc,EAAE,sDAAsD,4BAA4B,EAAE;AAAA,IACxG,CACD;AACD,WAAO,EAAE,WAAW,MAAM,QAAQ,aAAa,KAAK;AAAA,EACtD,SAAS,OAAO;AACd,0BAAsB,OAAO,CAAC;AAC9B,UAAM;AAAA,EACR;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -42,8 +42,7 @@ function CreateWorkflowDefinitionPage() {
|
|
|
42
42
|
[t]
|
|
43
43
|
);
|
|
44
44
|
return /* @__PURE__ */ jsx(Page, { children: /* @__PURE__ */ jsxs(PageBody, { children: [
|
|
45
|
-
/* @__PURE__ */ jsxs(Alert, { variant: "info", className: "mb-6", children: [
|
|
46
|
-
/* @__PURE__ */ jsx(Zap, { className: "w-4 h-4" }),
|
|
45
|
+
/* @__PURE__ */ jsxs(Alert, { variant: "info", icon: /* @__PURE__ */ jsx(Zap, { "aria-hidden": "true" }), className: "mb-6", children: [
|
|
47
46
|
/* @__PURE__ */ jsx(AlertTitle, { children: t("workflows.create.eventTriggersTitle") }),
|
|
48
47
|
/* @__PURE__ */ jsx(AlertDescription, { children: t("workflows.create.eventTriggersDescription") })
|
|
49
48
|
] }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/modules/workflows/backend/definitions/create/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 { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n workflowDefinitionFormSchema,\n createFormGroups,\n createFieldDefinitions,\n defaultFormValues,\n buildWorkflowPayload,\n type WorkflowDefinitionFormValues,\n} from '../../../components/formConfig'\nimport { StepsEditor } from '../../../components/StepsEditor'\nimport { TransitionsEditor } from '../../../components/TransitionsEditor'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Zap } from 'lucide-react'\nimport { formatWorkflowValidationError } from '../../../lib/format-validation-error'\n\nexport default function CreateWorkflowDefinitionPage() {\n const router = useRouter()\n const t = useT()\n\n const handleSubmit = async (values: WorkflowDefinitionFormValues) => {\n const payload = buildWorkflowPayload(values)\n\n const response = await apiFetch('/api/workflows/definitions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n const errorBody = await readJsonSafe<{ error?: string; details?: Array<{ path?: Array<string | number>; message?: string }> }>(response, null)\n throw new Error(formatWorkflowValidationError(errorBody, t('workflows.errors.createFailed')))\n }\n\n router.push('/backend/definitions')\n router.refresh()\n }\n\n const fields = React.useMemo(() => createFieldDefinitions(t), [t])\n\n const formGroups = React.useMemo(\n () => createFormGroups(t, StepsEditor, TransitionsEditor),\n [t]\n )\n\n return (\n <Page>\n <PageBody>\n <Alert variant=\"info\"
|
|
5
|
-
"mappings": ";AAuDQ,
|
|
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 { CrudForm } from '@open-mercato/ui/backend/CrudForm'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { readJsonSafe } from '@open-mercato/ui/backend/utils/serverErrors'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport {\n workflowDefinitionFormSchema,\n createFormGroups,\n createFieldDefinitions,\n defaultFormValues,\n buildWorkflowPayload,\n type WorkflowDefinitionFormValues,\n} from '../../../components/formConfig'\nimport { StepsEditor } from '../../../components/StepsEditor'\nimport { TransitionsEditor } from '../../../components/TransitionsEditor'\nimport { Alert, AlertDescription, AlertTitle } from '@open-mercato/ui/primitives/alert'\nimport { Zap } from 'lucide-react'\nimport { formatWorkflowValidationError } from '../../../lib/format-validation-error'\n\nexport default function CreateWorkflowDefinitionPage() {\n const router = useRouter()\n const t = useT()\n\n const handleSubmit = async (values: WorkflowDefinitionFormValues) => {\n const payload = buildWorkflowPayload(values)\n\n const response = await apiFetch('/api/workflows/definitions', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n })\n\n if (!response.ok) {\n const errorBody = await readJsonSafe<{ error?: string; details?: Array<{ path?: Array<string | number>; message?: string }> }>(response, null)\n throw new Error(formatWorkflowValidationError(errorBody, t('workflows.errors.createFailed')))\n }\n\n router.push('/backend/definitions')\n router.refresh()\n }\n\n const fields = React.useMemo(() => createFieldDefinitions(t), [t])\n\n const formGroups = React.useMemo(\n () => createFormGroups(t, StepsEditor, TransitionsEditor),\n [t]\n )\n\n return (\n <Page>\n <PageBody>\n <Alert variant=\"info\" icon={<Zap aria-hidden=\"true\" />} className=\"mb-6\">\n <AlertTitle>{t('workflows.create.eventTriggersTitle')}</AlertTitle>\n <AlertDescription>\n {t('workflows.create.eventTriggersDescription')}\n </AlertDescription>\n </Alert>\n <CrudForm\n title={t('workflows.create.title')}\n backHref=\"/backend/definitions\"\n schema={workflowDefinitionFormSchema}\n fields={fields}\n initialValues={defaultFormValues}\n onSubmit={handleSubmit}\n cancelHref=\"/backend/definitions\"\n groups={formGroups}\n submitLabel={t('workflows.form.create')}\n />\n </PageBody>\n </Page>\n )\n}\n"],
|
|
5
|
+
"mappings": ";AAuDQ,SAA4B,KAA5B;AArDR,YAAY,WAAW;AACvB,SAAS,iBAAiB;AAC1B,SAAS,MAAM,gBAAgB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,OAAO,kBAAkB,kBAAkB;AACpD,SAAS,WAAW;AACpB,SAAS,qCAAqC;AAE/B,SAAR,+BAAgD;AACrD,QAAM,SAAS,UAAU;AACzB,QAAM,IAAI,KAAK;AAEf,QAAM,eAAe,OAAO,WAAyC;AACnE,UAAM,UAAU,qBAAqB,MAAM;AAE3C,UAAM,WAAW,MAAM,SAAS,8BAA8B;AAAA,MAC5D,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,IAC9B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,aAAuG,UAAU,IAAI;AAC7I,YAAM,IAAI,MAAM,8BAA8B,WAAW,EAAE,+BAA+B,CAAC,CAAC;AAAA,IAC9F;AAEA,WAAO,KAAK,sBAAsB;AAClC,WAAO,QAAQ;AAAA,EACjB;AAEA,QAAM,SAAS,MAAM,QAAQ,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC;AAEjE,QAAM,aAAa,MAAM;AAAA,IACvB,MAAM,iBAAiB,GAAG,aAAa,iBAAiB;AAAA,IACxD,CAAC,CAAC;AAAA,EACJ;AAEA,SACE,oBAAC,QACC,+BAAC,YACC;AAAA,yBAAC,SAAM,SAAQ,QAAO,MAAM,oBAAC,OAAI,eAAY,QAAO,GAAI,WAAU,QAChE;AAAA,0BAAC,cAAY,YAAE,qCAAqC,GAAE;AAAA,MACtD,oBAAC,oBACE,YAAE,2CAA2C,GAChD;AAAA,OACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,wBAAwB;AAAA,QACjC,UAAS;AAAA,QACT,QAAQ;AAAA,QACR;AAAA,QACA,eAAe;AAAA,QACf,UAAU;AAAA,QACV,YAAW;AAAA,QACX,QAAQ;AAAA,QACR,aAAa,EAAE,uBAAuB;AAAA;AAAA,IACxC;AAAA,KACF,GACF;AAEJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -35,7 +35,7 @@ import { apiCall, withScopedApiRequestHeaders } from "@open-mercato/ui/backend/u
|
|
|
35
35
|
import { buildOptimisticLockHeader } from "@open-mercato/ui/backend/utils/optimisticLock";
|
|
36
36
|
import { surfaceRecordConflict } from "@open-mercato/ui/backend/conflicts";
|
|
37
37
|
import { flash } from "@open-mercato/ui/backend/FlashMessages";
|
|
38
|
-
import { CircleQuestionMark,
|
|
38
|
+
import { CircleQuestionMark, PanelTopClose, PanelTopOpen, Play, Save, Trash2 } from "lucide-react";
|
|
39
39
|
import { NODE_TYPE_ICONS, NODE_TYPE_COLORS, NODE_TYPE_LABELS } from "../../../lib/node-type-icons.js";
|
|
40
40
|
import { DefinitionTriggersEditor } from "../../../components/DefinitionTriggersEditor.js";
|
|
41
41
|
import { MobileVisualEditor } from "../../../components/mobile/MobileVisualEditor.js";
|
|
@@ -996,7 +996,6 @@ function VisualEditorPage() {
|
|
|
996
996
|
)
|
|
997
997
|
] }),
|
|
998
998
|
/* @__PURE__ */ jsxs(Alert, { variant: "info", className: "mt-6", children: [
|
|
999
|
-
/* @__PURE__ */ jsx(Info, { className: "size-4" }),
|
|
1000
999
|
/* @__PURE__ */ jsx(AlertTitle, { className: "text-xs", children: t("workflows.visualEditor.howToUse", "How to use:") }),
|
|
1001
1000
|
/* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxs("ul", { className: "list-inside list-disc space-y-1 text-xs", children: [
|
|
1002
1001
|
/* @__PURE__ */ jsx("li", { children: t("workflows.visualEditor.hint.addSteps", "Click step types to add them") }),
|