@agent-native/scheduling 0.1.10 → 0.1.12

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.
Files changed (183) hide show
  1. package/dist/actions/accept-team-invite.d.ts +5 -1
  2. package/dist/actions/accept-team-invite.d.ts.map +1 -1
  3. package/dist/actions/add-booking-attendee.d.ts +8 -1
  4. package/dist/actions/add-booking-attendee.d.ts.map +1 -1
  5. package/dist/actions/add-booking-note.d.ts +6 -1
  6. package/dist/actions/add-booking-note.d.ts.map +1 -1
  7. package/dist/actions/add-date-override.d.ts +10 -1
  8. package/dist/actions/add-date-override.d.ts.map +1 -1
  9. package/dist/actions/add-private-link.d.ts +8 -1
  10. package/dist/actions/add-private-link.d.ts.map +1 -1
  11. package/dist/actions/assign-round-robin-host.d.ts +6 -1
  12. package/dist/actions/assign-round-robin-host.d.ts.map +1 -1
  13. package/dist/actions/cancel-booking.d.ts +8 -1
  14. package/dist/actions/cancel-booking.d.ts.map +1 -1
  15. package/dist/actions/check-availability.d.ts +12 -1
  16. package/dist/actions/check-availability.d.ts.map +1 -1
  17. package/dist/actions/confirm-booking.d.ts +5 -1
  18. package/dist/actions/confirm-booking.d.ts.map +1 -1
  19. package/dist/actions/connect-calendar.d.ts +7 -1
  20. package/dist/actions/connect-calendar.d.ts.map +1 -1
  21. package/dist/actions/connect-video.d.ts +7 -1
  22. package/dist/actions/connect-video.d.ts.map +1 -1
  23. package/dist/actions/create-booking.d.ts +20 -1
  24. package/dist/actions/create-booking.d.ts.map +1 -1
  25. package/dist/actions/create-event-type.d.ts +17 -1
  26. package/dist/actions/create-event-type.d.ts.map +1 -1
  27. package/dist/actions/create-host-group.d.ts +7 -1
  28. package/dist/actions/create-host-group.d.ts.map +1 -1
  29. package/dist/actions/create-routing-form.d.ts +10 -1
  30. package/dist/actions/create-routing-form.d.ts.map +1 -1
  31. package/dist/actions/create-schedule.d.ts +14 -1
  32. package/dist/actions/create-schedule.d.ts.map +1 -1
  33. package/dist/actions/create-team.d.ts +11 -1
  34. package/dist/actions/create-team.d.ts.map +1 -1
  35. package/dist/actions/create-workflow.d.ts +18 -1
  36. package/dist/actions/create-workflow.d.ts.map +1 -1
  37. package/dist/actions/delete-event-type.d.ts +5 -1
  38. package/dist/actions/delete-event-type.d.ts.map +1 -1
  39. package/dist/actions/delete-routing-form.d.ts +5 -1
  40. package/dist/actions/delete-routing-form.d.ts.map +1 -1
  41. package/dist/actions/delete-schedule.d.ts +5 -1
  42. package/dist/actions/delete-schedule.d.ts.map +1 -1
  43. package/dist/actions/delete-workflow.d.ts +5 -1
  44. package/dist/actions/delete-workflow.d.ts.map +1 -1
  45. package/dist/actions/disconnect-calendar.d.ts +5 -1
  46. package/dist/actions/disconnect-calendar.d.ts.map +1 -1
  47. package/dist/actions/duplicate-event-type.d.ts +7 -1
  48. package/dist/actions/duplicate-event-type.d.ts.map +1 -1
  49. package/dist/actions/export-bookings-csv.d.ts +8 -1
  50. package/dist/actions/export-bookings-csv.d.ts.map +1 -1
  51. package/dist/actions/find-available-slot.d.ts +9 -1
  52. package/dist/actions/find-available-slot.d.ts.map +1 -1
  53. package/dist/actions/get-availability.d.ts +7 -1
  54. package/dist/actions/get-availability.d.ts.map +1 -1
  55. package/dist/actions/get-booking.d.ts +5 -1
  56. package/dist/actions/get-booking.d.ts.map +1 -1
  57. package/dist/actions/get-event-type.d.ts +8 -1
  58. package/dist/actions/get-event-type.d.ts.map +1 -1
  59. package/dist/actions/install-conferencing-app.d.ts +5 -1
  60. package/dist/actions/install-conferencing-app.d.ts.map +1 -1
  61. package/dist/actions/invite-team-member.d.ts +8 -1
  62. package/dist/actions/invite-team-member.d.ts.map +1 -1
  63. package/dist/actions/list-bookings.d.ts +11 -1
  64. package/dist/actions/list-bookings.d.ts.map +1 -1
  65. package/dist/actions/list-calendar-integrations.d.ts +7 -1
  66. package/dist/actions/list-calendar-integrations.d.ts.map +1 -1
  67. package/dist/actions/list-event-types.d.ts +6 -1
  68. package/dist/actions/list-event-types.d.ts.map +1 -1
  69. package/dist/actions/list-routing-form-responses.d.ts +6 -1
  70. package/dist/actions/list-routing-form-responses.d.ts.map +1 -1
  71. package/dist/actions/list-routing-forms.d.ts +5 -1
  72. package/dist/actions/list-routing-forms.d.ts.map +1 -1
  73. package/dist/actions/list-schedules.d.ts +3 -1
  74. package/dist/actions/list-schedules.d.ts.map +1 -1
  75. package/dist/actions/list-selected-calendars.d.ts +11 -1
  76. package/dist/actions/list-selected-calendars.d.ts.map +1 -1
  77. package/dist/actions/list-workflows.d.ts +5 -1
  78. package/dist/actions/list-workflows.d.ts.map +1 -1
  79. package/dist/actions/mark-no-show.d.ts +6 -1
  80. package/dist/actions/mark-no-show.d.ts.map +1 -1
  81. package/dist/actions/refresh-busy-times.d.ts +6 -1
  82. package/dist/actions/refresh-busy-times.d.ts.map +1 -1
  83. package/dist/actions/remove-booking-attendee.d.ts +6 -1
  84. package/dist/actions/remove-booking-attendee.d.ts.map +1 -1
  85. package/dist/actions/remove-date-override.d.ts +6 -1
  86. package/dist/actions/remove-date-override.d.ts.map +1 -1
  87. package/dist/actions/remove-team-member.d.ts +6 -1
  88. package/dist/actions/remove-team-member.d.ts.map +1 -1
  89. package/dist/actions/reorder-event-types.d.ts +5 -1
  90. package/dist/actions/reorder-event-types.d.ts.map +1 -1
  91. package/dist/actions/reschedule-booking.d.ts +10 -1
  92. package/dist/actions/reschedule-booking.d.ts.map +1 -1
  93. package/dist/actions/revoke-private-link.d.ts +5 -1
  94. package/dist/actions/revoke-private-link.d.ts.map +1 -1
  95. package/dist/actions/send-reschedule-link.d.ts +5 -1
  96. package/dist/actions/send-reschedule-link.d.ts.map +1 -1
  97. package/dist/actions/set-appearance.d.ts +8 -1
  98. package/dist/actions/set-appearance.d.ts.map +1 -1
  99. package/dist/actions/set-default-conferencing-app.d.ts +5 -1
  100. package/dist/actions/set-default-conferencing-app.d.ts.map +1 -1
  101. package/dist/actions/set-default-schedule.d.ts +5 -1
  102. package/dist/actions/set-default-schedule.d.ts.map +1 -1
  103. package/dist/actions/set-destination-calendar.d.ts +7 -1
  104. package/dist/actions/set-destination-calendar.d.ts.map +1 -1
  105. package/dist/actions/set-event-type-hosts.d.ts +12 -1
  106. package/dist/actions/set-event-type-hosts.d.ts.map +1 -1
  107. package/dist/actions/set-event-type-location.d.ts +6 -1
  108. package/dist/actions/set-event-type-location.d.ts.map +1 -1
  109. package/dist/actions/set-host-availability-override.d.ts +7 -1
  110. package/dist/actions/set-host-availability-override.d.ts.map +1 -1
  111. package/dist/actions/set-team-branding.d.ts +11 -1
  112. package/dist/actions/set-team-branding.d.ts.map +1 -1
  113. package/dist/actions/submit-routing-form-response.d.ts +10 -1
  114. package/dist/actions/submit-routing-form-response.d.ts.map +1 -1
  115. package/dist/actions/toggle-event-type-hidden.d.ts +6 -1
  116. package/dist/actions/toggle-event-type-hidden.d.ts.map +1 -1
  117. package/dist/actions/toggle-selected-calendar.d.ts +7 -1
  118. package/dist/actions/toggle-selected-calendar.d.ts.map +1 -1
  119. package/dist/actions/toggle-workflow.d.ts +6 -1
  120. package/dist/actions/toggle-workflow.d.ts.map +1 -1
  121. package/dist/actions/update-event-type.d.ts +38 -1
  122. package/dist/actions/update-event-type.d.ts.map +1 -1
  123. package/dist/actions/update-member-role.d.ts +7 -1
  124. package/dist/actions/update-member-role.d.ts.map +1 -1
  125. package/dist/actions/update-profile.d.ts +14 -1
  126. package/dist/actions/update-profile.d.ts.map +1 -1
  127. package/dist/actions/update-routing-form.d.ts +11 -1
  128. package/dist/actions/update-routing-form.d.ts.map +1 -1
  129. package/dist/actions/update-schedule.d.ts +22 -1
  130. package/dist/actions/update-schedule.d.ts.map +1 -1
  131. package/dist/actions/update-workflow.d.ts +19 -1
  132. package/dist/actions/update-workflow.d.ts.map +1 -1
  133. package/dist/react/components/SlotPicker.d.ts.map +1 -1
  134. package/dist/react/components/SlotPicker.js +3 -1
  135. package/dist/react/components/SlotPicker.js.map +1 -1
  136. package/dist/react/components/booking-links/AvailabilityEditor.d.ts +2 -1
  137. package/dist/react/components/booking-links/AvailabilityEditor.d.ts.map +1 -1
  138. package/dist/react/components/booking-links/AvailabilityEditor.js +28 -22
  139. package/dist/react/components/booking-links/AvailabilityEditor.js.map +1 -1
  140. package/dist/react/components/booking-links/BookingLinkCreateDialog.d.ts.map +1 -1
  141. package/dist/react/components/booking-links/BookingLinkCreateDialog.js +6 -4
  142. package/dist/react/components/booking-links/BookingLinkCreateDialog.js.map +1 -1
  143. package/dist/react/components/booking-links/ConferencingSelector.d.ts.map +1 -1
  144. package/dist/react/components/booking-links/ConferencingSelector.js +25 -19
  145. package/dist/react/components/booking-links/ConferencingSelector.js.map +1 -1
  146. package/dist/react/components/booking-links/CustomFieldsEditor.d.ts.map +1 -1
  147. package/dist/react/components/booking-links/CustomFieldsEditor.js +38 -24
  148. package/dist/react/components/booking-links/CustomFieldsEditor.js.map +1 -1
  149. package/dist/react/components/booking-links/DurationPicker.d.ts.map +1 -1
  150. package/dist/react/components/booking-links/DurationPicker.js +6 -2
  151. package/dist/react/components/booking-links/DurationPicker.js.map +1 -1
  152. package/dist/react/components/booking-links/SlugEditor.d.ts.map +1 -1
  153. package/dist/react/components/booking-links/SlugEditor.js +5 -3
  154. package/dist/react/components/booking-links/SlugEditor.js.map +1 -1
  155. package/dist/react/hooks/useEventType.d.ts +2 -2
  156. package/dist/react/hooks/useReschedule.d.ts +2 -2
  157. package/dist/react/i18n.d.ts +103 -0
  158. package/dist/react/i18n.d.ts.map +1 -0
  159. package/dist/react/i18n.js +970 -0
  160. package/dist/react/i18n.js.map +1 -0
  161. package/dist/schema/bookings.d.ts +49 -49
  162. package/dist/schema/calendar-cache.d.ts +8 -8
  163. package/dist/schema/credentials.d.ts +35 -35
  164. package/dist/schema/event-types.d.ts +42 -42
  165. package/dist/schema/routing-forms.d.ts +20 -20
  166. package/dist/schema/schedules.d.ts +31 -31
  167. package/dist/schema/teams.d.ts +19 -19
  168. package/dist/schema/workflows.d.ts +49 -49
  169. package/dist/server/availability-engine.d.ts.map +1 -1
  170. package/dist/server/availability-engine.js.map +1 -1
  171. package/dist/server/bookings-repo.d.ts.map +1 -1
  172. package/dist/server/bookings-repo.js.map +1 -1
  173. package/package.json +10 -11
  174. package/src/react/components/SlotPicker.tsx +6 -1
  175. package/src/react/components/booking-links/AvailabilityEditor.tsx +48 -27
  176. package/src/react/components/booking-links/BookingLinkCreateDialog.tsx +15 -13
  177. package/src/react/components/booking-links/ConferencingSelector.tsx +35 -30
  178. package/src/react/components/booking-links/CustomFieldsEditor.tsx +68 -49
  179. package/src/react/components/booking-links/DurationPicker.tsx +8 -4
  180. package/src/react/components/booking-links/SlugEditor.tsx +7 -5
  181. package/src/react/i18n.ts +1044 -0
  182. package/src/server/availability-engine.ts +3 -1
  183. package/src/server/bookings-repo.ts +4 -2
@@ -11,6 +11,8 @@
11
11
  */
12
12
  import { Input } from "@/components/ui/input";
13
13
  import { Switch } from "@/components/ui/switch";
14
+ import { schedulingMessage, useSchedulingT } from "../../i18n.js";
15
+ import type { LocaleCode } from "@agent-native/core/client";
14
16
 
15
17
  export type DayKey =
16
18
  | "monday"
@@ -33,14 +35,18 @@ export interface DaySchedule {
33
35
 
34
36
  export type WeeklySchedule = Record<DayKey, DaySchedule>;
35
37
 
36
- const DAYS: { key: DayKey; label: string; short: string }[] = [
37
- { key: "monday", label: "Monday", short: "Mon" },
38
- { key: "tuesday", label: "Tuesday", short: "Tue" },
39
- { key: "wednesday", label: "Wednesday", short: "Wed" },
40
- { key: "thursday", label: "Thursday", short: "Thu" },
41
- { key: "friday", label: "Friday", short: "Fri" },
42
- { key: "saturday", label: "Saturday", short: "Sat" },
43
- { key: "sunday", label: "Sunday", short: "Sun" },
38
+ const DAYS: {
39
+ key: DayKey;
40
+ labelKey: Parameters<ReturnType<typeof useSchedulingT>>[0];
41
+ shortKey: Parameters<ReturnType<typeof useSchedulingT>>[0];
42
+ }[] = [
43
+ { key: "monday", labelKey: "monday", shortKey: "mon" },
44
+ { key: "tuesday", labelKey: "tuesday", shortKey: "tue" },
45
+ { key: "wednesday", labelKey: "wednesday", shortKey: "wed" },
46
+ { key: "thursday", labelKey: "thursday", shortKey: "thu" },
47
+ { key: "friday", labelKey: "friday", shortKey: "fri" },
48
+ { key: "saturday", labelKey: "saturday", shortKey: "sat" },
49
+ { key: "sunday", labelKey: "sunday", shortKey: "sun" },
44
50
  ];
45
51
 
46
52
  export interface AvailabilityEditorProps {
@@ -52,6 +58,7 @@ export function AvailabilityEditor({
52
58
  value,
53
59
  onChange,
54
60
  }: AvailabilityEditorProps) {
61
+ const t = useSchedulingT();
55
62
  const setDay = (day: DayKey, patch: Partial<DaySchedule>) => {
56
63
  onChange({
57
64
  ...value,
@@ -74,7 +81,9 @@ export function AvailabilityEditor({
74
81
 
75
82
  return (
76
83
  <div className="space-y-2.5">
77
- {DAYS.map(({ key, label, short }) => {
84
+ {DAYS.map(({ key, labelKey, shortKey }) => {
85
+ const label = t(labelKey);
86
+ const short = t(shortKey);
78
87
  const day = value[key] ?? { enabled: false, slots: [] };
79
88
  const slot = day.slots[0] ?? { start: "09:00", end: "17:00" };
80
89
  return (
@@ -86,7 +95,7 @@ export function AvailabilityEditor({
86
95
  <Switch
87
96
  checked={day.enabled}
88
97
  onCheckedChange={(checked) => setDay(key, { enabled: checked })}
89
- aria-label={`Toggle ${label}`}
98
+ aria-label={t("toggleDay", { day: label })}
90
99
  />
91
100
  <span className="text-sm font-medium">
92
101
  <span className="hidden sm:inline">{label}</span>
@@ -102,7 +111,7 @@ export function AvailabilityEditor({
102
111
  onChange={(e) => setSlot(key, "start", e.target.value)}
103
112
  className="w-28 sm:w-32"
104
113
  />
105
- <span className="text-muted-foreground">to</span>
114
+ <span className="text-muted-foreground">{t("to")}</span>
106
115
  <Input
107
116
  type="time"
108
117
  value={slot.end}
@@ -111,7 +120,9 @@ export function AvailabilityEditor({
111
120
  />
112
121
  </div>
113
122
  ) : (
114
- <span className="text-sm text-muted-foreground">Unavailable</span>
123
+ <span className="text-sm text-muted-foreground">
124
+ {t("unavailable")}
125
+ </span>
115
126
  )}
116
127
  </div>
117
128
  );
@@ -124,7 +135,10 @@ export function AvailabilityEditor({
124
135
  * Summarize a `WeeklySchedule` in a short phrase, e.g. "Weekdays, 9 am - 5 pm".
125
136
  * Useful for list-row subtitles.
126
137
  */
127
- export function summarizeAvailability(ws: WeeklySchedule): string {
138
+ export function summarizeAvailability(
139
+ ws: WeeklySchedule,
140
+ locale: LocaleCode = "en-US",
141
+ ): string {
128
142
  const weekdayKeys: DayKey[] = [
129
143
  "monday",
130
144
  "tuesday",
@@ -136,7 +150,8 @@ export function summarizeAvailability(ws: WeeklySchedule): string {
136
150
  const allDays: DayKey[] = [...weekdayKeys, ...weekendKeys];
137
151
 
138
152
  const enabled = allDays.filter((d) => ws[d]?.enabled);
139
- if (enabled.length === 0) return "No availability set";
153
+ if (enabled.length === 0)
154
+ return schedulingMessage(locale, "noAvailabilitySet");
140
155
 
141
156
  const weekdaysOn = weekdayKeys.every((d) => ws[d]?.enabled);
142
157
  const weekendsOn = weekendKeys.every((d) => ws[d]?.enabled);
@@ -144,20 +159,26 @@ export function summarizeAvailability(ws: WeeklySchedule): string {
144
159
  const weekendsOff = weekendKeys.every((d) => !ws[d]?.enabled);
145
160
 
146
161
  let dayLabel: string;
147
- if (weekdaysOn && weekendsOn) dayLabel = "Every day";
148
- else if (weekdaysOn && weekendsOff) dayLabel = "Weekdays";
149
- else if (weekdaysOff && weekendsOn) dayLabel = "Weekends";
162
+ if (weekdaysOn && weekendsOn)
163
+ dayLabel = schedulingMessage(locale, "everyDay");
164
+ else if (weekdaysOn && weekendsOff)
165
+ dayLabel = schedulingMessage(locale, "weekdays");
166
+ else if (weekdaysOff && weekendsOn)
167
+ dayLabel = schedulingMessage(locale, "weekends");
150
168
  else {
151
- const shortNames: Record<DayKey, string> = {
152
- monday: "Mon",
153
- tuesday: "Tue",
154
- wednesday: "Wed",
155
- thursday: "Thu",
156
- friday: "Fri",
157
- saturday: "Sat",
158
- sunday: "Sun",
159
- };
160
- dayLabel = enabled.map((d) => shortNames[d]).join(", ");
169
+ const shortNames: Record<DayKey, Parameters<typeof schedulingMessage>[1]> =
170
+ {
171
+ monday: "mon",
172
+ tuesday: "tue",
173
+ wednesday: "wed",
174
+ thursday: "thu",
175
+ friday: "fri",
176
+ saturday: "sat",
177
+ sunday: "sun",
178
+ };
179
+ dayLabel = enabled
180
+ .map((d) => schedulingMessage(locale, shortNames[d]))
181
+ .join(", ");
161
182
  }
162
183
 
163
184
  const slot = ws[enabled[0]].slots[0];
@@ -22,6 +22,7 @@ import { Button } from "@/components/ui/button";
22
22
  import { Input } from "@/components/ui/input";
23
23
  import { Label } from "@/components/ui/label";
24
24
  import { Textarea } from "@/components/ui/textarea";
25
+ import { useSchedulingT } from "../../i18n.js";
25
26
 
26
27
  export interface BookingLinkCreateDraft {
27
28
  title: string;
@@ -54,13 +55,14 @@ function slugify(value: string) {
54
55
  }
55
56
 
56
57
  export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
58
+ const t = useSchedulingT();
57
59
  const {
58
60
  open,
59
61
  onOpenChange,
60
62
  slugPrefix,
61
63
  defaultLength = 30,
62
64
  onSubmit,
63
- submitLabel = "Continue",
65
+ submitLabel = t("continue"),
64
66
  } = props;
65
67
 
66
68
  const [form, setForm] = useState<BookingLinkCreateDraft>({
@@ -100,14 +102,12 @@ export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
100
102
  <Dialog open={open} onOpenChange={onOpenChange}>
101
103
  <DialogContent>
102
104
  <DialogHeader>
103
- <DialogTitle>Add a new event type</DialogTitle>
104
- <DialogDescription>
105
- Create a new event type for people to book.
106
- </DialogDescription>
105
+ <DialogTitle>{t("addEventTypeTitle")}</DialogTitle>
106
+ <DialogDescription>{t("addEventTypeDescription")}</DialogDescription>
107
107
  </DialogHeader>
108
108
  <div className="space-y-4">
109
109
  <div className="space-y-1.5">
110
- <Label htmlFor="blc-title">Title</Label>
110
+ <Label htmlFor="blc-title">{t("title")}</Label>
111
111
  <Input
112
112
  id="blc-title"
113
113
  placeholder="Quick chat"
@@ -124,7 +124,7 @@ export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
124
124
  />
125
125
  </div>
126
126
  <div className="space-y-1.5">
127
- <Label htmlFor="blc-slug">URL</Label>
127
+ <Label htmlFor="blc-slug">{t("url")}</Label>
128
128
  <div className="flex rounded-md border border-input focus-within:ring-2 focus-within:ring-ring">
129
129
  <span className="flex items-center rounded-l-md bg-muted px-3 text-xs text-muted-foreground">
130
130
  {slugPrefix}
@@ -150,10 +150,10 @@ export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
150
150
  </div>
151
151
  </div>
152
152
  <div className="space-y-1.5">
153
- <Label htmlFor="blc-desc">Description</Label>
153
+ <Label htmlFor="blc-desc">{t("description")}</Label>
154
154
  <Textarea
155
155
  id="blc-desc"
156
- placeholder="A short description people will see."
156
+ placeholder={t("shortDescriptionPlaceholder")}
157
157
  rows={2}
158
158
  value={form.description}
159
159
  onChange={(e) =>
@@ -162,7 +162,7 @@ export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
162
162
  />
163
163
  </div>
164
164
  <div className="space-y-1.5">
165
- <Label htmlFor="blc-len">Duration</Label>
165
+ <Label htmlFor="blc-len">{t("duration")}</Label>
166
166
  <div className="flex items-center gap-2">
167
167
  <Input
168
168
  id="blc-len"
@@ -173,19 +173,21 @@ export function BookingLinkCreateDialog(props: BookingLinkCreateDialogProps) {
173
173
  setForm({ ...form, length: Number(e.currentTarget.value) })
174
174
  }
175
175
  />
176
- <span className="text-sm text-muted-foreground">minutes</span>
176
+ <span className="text-sm text-muted-foreground">
177
+ {t("minutes")}
178
+ </span>
177
179
  </div>
178
180
  </div>
179
181
  </div>
180
182
  <DialogFooter>
181
183
  <Button variant="outline" onClick={() => onOpenChange(false)}>
182
- Cancel
184
+ {t("cancel")}
183
185
  </Button>
184
186
  <Button
185
187
  onClick={submit}
186
188
  disabled={!form.title || !form.slug || submitting}
187
189
  >
188
- {submitting ? "Saving…" : submitLabel}
190
+ {submitting ? t("saving") : submitLabel}
189
191
  </Button>
190
192
  </DialogFooter>
191
193
  </DialogContent>
@@ -41,6 +41,7 @@ import {
41
41
  SelectItem,
42
42
  SelectTrigger,
43
43
  } from "@/components/ui/select";
44
+ import { useSchedulingT } from "../../i18n.js";
44
45
 
45
46
  export type ConferencingType = "none" | "google_meet" | "zoom" | "custom";
46
47
 
@@ -65,37 +66,38 @@ export interface ConferencingSelectorProps {
65
66
 
66
67
  const OPTIONS: {
67
68
  type: ConferencingType;
68
- label: string;
69
- description: string;
69
+ labelKey: Parameters<ReturnType<typeof useSchedulingT>>[0];
70
+ descriptionKey: Parameters<ReturnType<typeof useSchedulingT>>[0];
70
71
  Icon: ComponentType<{ className?: string }>;
71
72
  }[] = [
72
73
  {
73
74
  type: "none",
74
- label: "No conferencing",
75
- description: "In-person or other",
75
+ labelKey: "noConferencing",
76
+ descriptionKey: "inPersonOrOther",
76
77
  Icon: IconVideoOff,
77
78
  },
78
79
  {
79
80
  type: "google_meet",
80
- label: "Google Meet",
81
- description: "Auto-generate a Meet link",
81
+ labelKey: "googleMeet",
82
+ descriptionKey: "googleMeetDescription",
82
83
  Icon: IconBrandGoogle,
83
84
  },
84
85
  {
85
86
  type: "zoom",
86
- label: "Zoom",
87
- description: "Auto-create a meeting per booking",
87
+ labelKey: "zoom",
88
+ descriptionKey: "zoomDescription",
88
89
  Icon: IconBrandZoom,
89
90
  },
90
91
  {
91
92
  type: "custom",
92
- label: "Custom link",
93
- description: "Paste any meeting URL",
93
+ labelKey: "customLink",
94
+ descriptionKey: "customLinkDescription",
94
95
  Icon: IconLink,
95
96
  },
96
97
  ];
97
98
 
98
99
  export function ConferencingSelector(props: ConferencingSelectorProps) {
100
+ const t = useSchedulingT();
99
101
  const id = useId();
100
102
  const {
101
103
  value,
@@ -122,7 +124,7 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
122
124
  {!hideLabel && (
123
125
  <Label className="flex items-center gap-1.5">
124
126
  <IconVideo className="h-4 w-4" />
125
- Conferencing
127
+ {t("conferencing")}
126
128
  </Label>
127
129
  )}
128
130
 
@@ -141,7 +143,7 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
141
143
  <div className="min-w-0">
142
144
  <div className="flex items-center gap-2">
143
145
  <span className="truncate font-medium">
144
- {selectedOption.label}
146
+ {t(selectedOption.labelKey)}
145
147
  </span>
146
148
  {selectedStatus === "connected" &&
147
149
  selectedOption.type !== "none" &&
@@ -151,14 +153,16 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
151
153
  className="h-5 gap-1 text-[10px] font-normal"
152
154
  >
153
155
  <IconCheck className="h-3 w-3" />
154
- Connected
156
+ {t("connected")}
155
157
  </Badge>
156
158
  )}
157
159
  </div>
158
160
  <p className="truncate text-xs text-muted-foreground">
159
161
  {selectedStatus === "not-configured"
160
- ? `${selectedOption.label} is not configured on this server.`
161
- : selectedOption.description}
162
+ ? t("providerNotConfigured", {
163
+ provider: t(selectedOption.labelKey),
164
+ })
165
+ : t(selectedOption.descriptionKey)}
162
166
  </p>
163
167
  </div>
164
168
  </div>
@@ -178,19 +182,21 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
178
182
  <opt.Icon className="mt-0.5 h-4 w-4 shrink-0" />
179
183
  <div className="min-w-0">
180
184
  <div className="flex items-center gap-2">
181
- <span className="font-medium">{opt.label}</span>
185
+ <span className="font-medium">{t(opt.labelKey)}</span>
182
186
  {status === "connected" &&
183
187
  opt.type !== "none" &&
184
188
  opt.type !== "custom" && (
185
189
  <span className="text-[10px] text-muted-foreground">
186
- Connected
190
+ {t("connected")}
187
191
  </span>
188
192
  )}
189
193
  </div>
190
194
  <p className="text-xs text-muted-foreground">
191
195
  {isUnavailable
192
- ? `${opt.label} needs server OAuth credentials before it can be used.`
193
- : opt.description}
196
+ ? t("providerNeedsCredentials", {
197
+ provider: t(opt.labelKey),
198
+ })
199
+ : t(opt.descriptionKey)}
194
200
  </p>
195
201
  </div>
196
202
  </div>
@@ -205,10 +211,9 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
205
211
  <div className="rounded-md border border-border/60 bg-muted/30 p-3">
206
212
  <div className="flex flex-wrap items-center justify-between gap-2">
207
213
  <div className="min-w-0 flex-1">
208
- <p className="text-sm font-medium">Connect your Zoom account</p>
214
+ <p className="text-sm font-medium">{t("connectZoomAccount")}</p>
209
215
  <p className="text-xs text-muted-foreground">
210
- We'll create a real Zoom meeting for every booking — no need to
211
- paste a personal link.
216
+ {t("connectZoomAccountDescription")}
212
217
  </p>
213
218
  </div>
214
219
  <Button
@@ -218,13 +223,12 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
218
223
  disabled={zoomStatus === "not-configured"}
219
224
  >
220
225
  <IconBrandZoom className="mr-1.5 h-4 w-4" />
221
- Connect Zoom
226
+ {t("connectZoom")}
222
227
  </Button>
223
228
  </div>
224
229
  {zoomStatus === "not-configured" && (
225
230
  <p className="mt-2 text-[11px] text-muted-foreground">
226
- Ask your admin to set <code>ZOOM_CLIENT_ID</code> and{" "}
227
- <code>ZOOM_CLIENT_SECRET</code> to enable Zoom OAuth.
231
+ {t("zoomNotConfigured")}
228
232
  </p>
229
233
  )}
230
234
  </div>
@@ -237,10 +241,11 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
237
241
  <div className="rounded-md border border-border/60 bg-muted/30 p-3">
238
242
  <div className="flex flex-wrap items-center justify-between gap-2">
239
243
  <div className="min-w-0 flex-1">
240
- <p className="text-sm font-medium">Connect Google Calendar</p>
244
+ <p className="text-sm font-medium">
245
+ {t("connectGoogleCalendar")}
246
+ </p>
241
247
  <p className="text-xs text-muted-foreground">
242
- Meet links are auto-generated when the calendar event is
243
- created.
248
+ {t("connectGoogleCalendarDescription")}
244
249
  </p>
245
250
  </div>
246
251
  <Button
@@ -251,7 +256,7 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
251
256
  disabled={googleStatus === "not-configured"}
252
257
  >
253
258
  <IconBrandGoogle className="mr-1.5 h-4 w-4" />
254
- Connect Google
259
+ {t("connectGoogle")}
255
260
  </Button>
256
261
  </div>
257
262
  </div>
@@ -261,7 +266,7 @@ export function ConferencingSelector(props: ConferencingSelectorProps) {
261
266
  {value.type === "custom" && (
262
267
  <div className="space-y-1.5">
263
268
  <Label htmlFor={`${id}-url`} className="text-xs">
264
- Meeting URL
269
+ {t("meetingUrl")}
265
270
  </Label>
266
271
  <Input
267
272
  id={`${id}-url`}