starterDesign.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import type { TemplateConfig } from '@/features/vehicles/Components/invoice-pdf/types'
  2. import {
  3. DESIGNER_LAYOUT_VERSION,
  4. type InvoiceLayoutConfig,
  5. invoiceLayoutConfigSchema,
  6. } from '@/features/settings/Schema/invoiceLayoutSchema'
  7. import { buildLayoutFromPreset, layoutPresets } from '@/features/settings/Schema/layoutPresets'
  8. import { SETTING_KEYS } from '@/features/settings/Schema/settingsSchema'
  9. /**
  10. * The template a new workshop's invoices and quotes start on: Compact, the
  11. * dense one-page sheet. Workshops made before this keep whatever they print
  12. * now; only a workshop made by onboarding gets these settings, and it can
  13. * pick any other template in Settings, Templates.
  14. */
  15. export const STARTER_PRESET_ID = 'compact'
  16. function starterPreset() {
  17. const preset = layoutPresets.find((p) => p.id === STARTER_PRESET_ID)
  18. if (!preset) throw new Error(`Starter template "${STARTER_PRESET_ID}" is missing`)
  19. return preset
  20. }
  21. /**
  22. * The layout as the designer would save it, stamped so it prints as a
  23. * designer layout, with the title strip on. The Compact template leaves the
  24. * strip out, and a sheet without it prints no title, no number and no dates.
  25. * Only new workshops get this; the template itself is left as it is, so no
  26. * existing workshop changes.
  27. */
  28. export function starterLayout(): InvoiceLayoutConfig {
  29. const layout = buildLayoutFromPreset(starterPreset())
  30. const ordered = [...layout.sections].sort((a, b) => a.order - b.order)
  31. const title = ordered.find((s) => s.id === 'document_title')
  32. const rest = ordered.filter((s) => s !== title)
  33. if (title)
  34. rest.splice(rest.findIndex((s) => s.id === 'header') + 1, 0, { ...title, visible: true })
  35. return invoiceLayoutConfigSchema.parse({
  36. ...layout,
  37. sections: rest.map((s, order) => ({ ...s, order })),
  38. version: DESIGNER_LAYOUT_VERSION,
  39. })
  40. }
  41. /** The look and layout together, as the print builders take them. */
  42. export function starterTemplate(): TemplateConfig {
  43. const { template } = starterPreset()
  44. return {
  45. primaryColor: template.primaryColor,
  46. headerStyle: template.headerStyle,
  47. fontFamily: template.fontFamily,
  48. layoutConfig: starterLayout(),
  49. }
  50. }
  51. /**
  52. * The settings rows that make the starter template the workshop's own, for
  53. * invoices and quotes: the same keys the designer writes when a template is
  54. * saved, with the template marked as the one in use.
  55. */
  56. export function starterDesignSettings(): Record<string, string> {
  57. const { template } = starterPreset()
  58. const layout = JSON.stringify(starterLayout())
  59. const rows: Record<string, string> = {
  60. [SETTING_KEYS.INVOICE_LAYOUT_CONFIG]: layout,
  61. [SETTING_KEYS.QUOTE_LAYOUT_CONFIG]: layout,
  62. }
  63. for (const prefix of ['invoice', 'quote']) {
  64. rows[`${prefix}.primaryColor`] = template.primaryColor
  65. rows[`${prefix}.headerStyle`] = template.headerStyle
  66. rows[`${prefix}.fontFamily`] = template.fontFamily
  67. rows[`${prefix}.activeDesign`] = `preset:${STARTER_PRESET_ID}`
  68. }
  69. return rows
  70. }