@fayz-ai/plugin-agenda 0.9.0 → 0.9.1
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/README.md +3 -3
- package/dist/bridges/create-financial-bridge.d.ts +1 -1
- package/dist/bridges/create-financial-bridge.d.ts.map +1 -1
- package/dist/bridges/financial-bridge.d.ts.map +1 -0
- package/dist/{chunk-Q2PAWBPR.js → chunk-76ZOHRBM.js} +2 -2
- package/dist/{chunk-Q2PAWBPR.js.map → chunk-76ZOHRBM.js.map} +1 -1
- package/dist/components/PaymentStatusBadge.d.ts +1 -1
- package/dist/components/PaymentStatusBadge.d.ts.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/{AgendaContext.d.ts → context.d.ts} +1 -1
- package/dist/context.d.ts.map +1 -0
- package/dist/data/registries.d.ts.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +170 -7
- package/dist/index.js.map +1 -1
- package/dist/lib/message-events.d.ts +12 -0
- package/dist/lib/message-events.d.ts.map +1 -0
- package/dist/public/{data.d.ts → data/index.d.ts} +4 -4
- package/dist/public/data/index.d.ts.map +1 -0
- package/dist/public/{data.supabase.d.ts → data/supabase.d.ts} +2 -2
- package/dist/public/data/supabase.d.ts.map +1 -0
- package/dist/public/{hooks.d.ts → hooks/index.d.ts} +4 -4
- package/dist/public/hooks/index.d.ts.map +1 -0
- package/dist/public/index.d.ts +4 -4
- package/dist/public/index.d.ts.map +1 -1
- package/dist/public/index.js +3 -3
- package/dist/public/index.js.map +1 -1
- package/dist/public/{format.d.ts → lib/format.d.ts} +1 -1
- package/dist/public/lib/format.d.ts.map +1 -0
- package/dist/public/views/BookingWidget.d.ts.map +1 -0
- package/dist/public/{steps → views/steps}/ContactStep.d.ts +1 -1
- package/dist/public/views/steps/ContactStep.d.ts.map +1 -0
- package/dist/public/{steps → views/steps}/DateTimeStep.d.ts +3 -3
- package/dist/public/views/steps/DateTimeStep.d.ts.map +1 -0
- package/dist/public/{steps → views/steps}/OverviewStep.d.ts +1 -1
- package/dist/public/views/steps/OverviewStep.d.ts.map +1 -0
- package/dist/public/{steps → views/steps}/PaymentStep.d.ts +1 -1
- package/dist/public/views/steps/PaymentStep.d.ts.map +1 -0
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/styles/calendar-styles.d.ts.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/{AgendaPage.d.ts → views/AgendaPage.d.ts} +3 -3
- package/dist/views/AgendaPage.d.ts.map +1 -0
- package/package.json +6 -9
- package/dist/AgendaContext.d.ts.map +0 -1
- package/dist/AgendaPage.d.ts.map +0 -1
- package/dist/calendar-styles.d.ts.map +0 -1
- package/dist/financial-bridge.d.ts.map +0 -1
- package/dist/public/BookingWidget.d.ts.map +0 -1
- package/dist/public/data.d.ts.map +0 -1
- package/dist/public/data.supabase.d.ts.map +0 -1
- package/dist/public/format.d.ts.map +0 -1
- package/dist/public/hooks.d.ts.map +0 -1
- package/dist/public/steps/ContactStep.d.ts.map +0 -1
- package/dist/public/steps/DateTimeStep.d.ts.map +0 -1
- package/dist/public/steps/OverviewStep.d.ts.map +0 -1
- package/dist/public/steps/PaymentStep.d.ts.map +0 -1
- package/dist/registries.d.ts.map +0 -1
- package/src/AgendaContext.tsx +0 -11
- package/src/AgendaPage.tsx +0 -33
- package/src/bridges/create-financial-bridge.ts +0 -296
- package/src/calendar-styles.css +0 -245
- package/src/calendar-styles.ts +0 -285
- package/src/components/AgendaGeneralSettings.tsx +0 -86
- package/src/components/AgendaMobileList.tsx +0 -103
- package/src/components/AppointmentModal.tsx +0 -1050
- package/src/components/AppointmentPopover.tsx +0 -231
- package/src/components/BookingPaymentPanel.tsx +0 -394
- package/src/components/CalendarSidebar.tsx +0 -119
- package/src/components/CalendarToolbar.tsx +0 -86
- package/src/components/EventContextMenu.tsx +0 -125
- package/src/components/FloatingPanel.tsx +0 -123
- package/src/components/MiniCalendar.tsx +0 -120
- package/src/components/PaymentStatusBadge.tsx +0 -62
- package/src/components/StatusBadge.tsx +0 -23
- package/src/config.ts +0 -368
- package/src/data/index.ts +0 -4
- package/src/data/mock.ts +0 -344
- package/src/data/supabase.ts +0 -636
- package/src/data/types.ts +0 -37
- package/src/financial-bridge.ts +0 -96
- package/src/hooks/useAgendaSettings.ts +0 -17
- package/src/index.ts +0 -297
- package/src/integrations/google-calendar/GoogleCalendarSettings.tsx +0 -136
- package/src/integrations/google-calendar/components/CalendarColorDot.tsx +0 -23
- package/src/integrations/google-calendar/components/ChannelMappingList.tsx +0 -329
- package/src/integrations/google-calendar/components/ImportEventsWizard.tsx +0 -215
- package/src/integrations/google-calendar/components/useAgendaLookups.ts +0 -100
- package/src/integrations/google-calendar/connector.ts +0 -20
- package/src/integrations/google-calendar/connectorDef.tsx +0 -185
- package/src/integrations/google-calendar/data/supabase.ts +0 -170
- package/src/integrations/google-calendar/data/tables.ts +0 -12
- package/src/integrations/google-calendar/index.ts +0 -45
- package/src/integrations/google-calendar/integration.test.ts +0 -199
- package/src/integrations/google-calendar/mapping.ts +0 -183
- package/src/integrations/google-calendar/migrations/001_google_calendar.sql +0 -97
- package/src/integrations/google-calendar/migrations/002_smart_sync.sql +0 -517
- package/src/integrations/google-calendar/migrations/003_plg_rename.sql +0 -273
- package/src/integrations/google-calendar/types.ts +0 -142
- package/src/lib/tenant.ts +0 -3
- package/src/locales/en.ts +0 -220
- package/src/locales/index.ts +0 -7
- package/src/locales/pt-BR.ts +0 -220
- package/src/migrations/000b_v_bookings_rename.sql +0 -21
- package/src/migrations/000c_dedupe_customer_phones.sql +0 -43
- package/src/migrations/001_public_booking.sql +0 -296
- package/src/migrations/002_v_bookings_compat.sql +0 -14
- package/src/migrations/003_public_client_kind.sql +0 -175
- package/src/migrations/004_public_booking_assignee.sql +0 -176
- package/src/migrations/005_agent_rpcs.sql +0 -168
- package/src/migrations/006_agent_rpc_localtime.sql +0 -181
- package/src/migrations/007_schedule_exception_precedence.sql +0 -290
- package/src/migrations/008_agent_rpc_exception_precedence.sql +0 -172
- package/src/migrations/009_public_booking_location.sql +0 -162
- package/src/migrations/010_public_service_curation.sql +0 -31
- package/src/migrations/011_default_assignee.sql +0 -167
- package/src/migrations/012_drop_legacy_booking_overload.sql +0 -29
- package/src/migrations/013_normalize_v_appointments.sql +0 -199
- package/src/migrations/014_agent_rpc_update_appointment.sql +0 -199
- package/src/migrations/index.ts +0 -2377
- package/src/public/BookingWidget.tsx +0 -324
- package/src/public/components/BrandHeader.tsx +0 -27
- package/src/public/components/ServiceCard.tsx +0 -39
- package/src/public/components/SidebarExtras.tsx +0 -30
- package/src/public/components/StepRailItem.tsx +0 -27
- package/src/public/components/SuccessPanel.tsx +0 -27
- package/src/public/components/SummaryRail.tsx +0 -90
- package/src/public/components/defaults.ts +0 -14
- package/src/public/context.tsx +0 -103
- package/src/public/createPublicBookingPlugin.ts +0 -281
- package/src/public/data.supabase.ts +0 -97
- package/src/public/data.ts +0 -105
- package/src/public/format.ts +0 -96
- package/src/public/hooks.ts +0 -110
- package/src/public/index.ts +0 -69
- package/src/public/steps/ContactStep.tsx +0 -184
- package/src/public/steps/DateTimeStep.tsx +0 -138
- package/src/public/steps/OverviewStep.tsx +0 -81
- package/src/public/steps/PaymentStep.tsx +0 -180
- package/src/public/types.ts +0 -250
- package/src/registries.ts +0 -35
- package/src/store.ts +0 -311
- package/src/types.ts +0 -273
- package/src/views/CalendarView.tsx +0 -1112
- package/src/views/ConfirmationsView.tsx +0 -155
- /package/dist/{financial-bridge.d.ts → bridges/financial-bridge.d.ts} +0 -0
- /package/dist/{registries.d.ts → data/registries.d.ts} +0 -0
- /package/dist/public/{BookingWidget.d.ts → views/BookingWidget.d.ts} +0 -0
- /package/dist/{calendar-styles.d.ts → styles/calendar-styles.d.ts} +0 -0
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
-- ---------------------------------------------------------------------------
|
|
2
|
-
-- 003_plg_rename.sql — standardize the Google Calendar connector objects onto
|
|
3
|
-
-- the platform `plg_<plugin>_` prefix (DATA-MODEL.md Ring 1).
|
|
4
|
-
--
|
|
5
|
-
-- calendar_integrations → plg_calendar_integrations
|
|
6
|
-
-- calendar_channels → plg_calendar_channels
|
|
7
|
-
-- calendar_sync_log → plg_calendar_sync_log
|
|
8
|
-
--
|
|
9
|
-
-- Legacy-pool remediation ONLY: 001/002 now create the prefixed names directly,
|
|
10
|
-
-- so fresh installs never reach a rename branch. Fully idempotent and guarded —
|
|
11
|
-
-- every RENAME fires only when the old object exists and the new one does not,
|
|
12
|
-
-- so re-running (or running on an already-prefixed pool) is a no-op.
|
|
13
|
-
--
|
|
14
|
-
-- A table RENAME preserves its data, RLS state, policies, grants, indexes,
|
|
15
|
-
-- constraints and triggers (they follow the table), so §1 only renames the
|
|
16
|
-
-- table + the explicitly-named indexes. §2 then re-points the SECURITY DEFINER
|
|
17
|
-
-- gcal_* functions whose bodies hard-code the old table names.
|
|
18
|
-
-- ---------------------------------------------------------------------------
|
|
19
|
-
|
|
20
|
-
-- ===========================================================================
|
|
21
|
-
-- §1 — Guarded table + index renames.
|
|
22
|
-
-- ===========================================================================
|
|
23
|
-
DO $$
|
|
24
|
-
BEGIN
|
|
25
|
-
IF to_regclass('public.calendar_integrations') IS NOT NULL
|
|
26
|
-
AND to_regclass('public.plg_calendar_integrations') IS NULL THEN
|
|
27
|
-
ALTER TABLE public.calendar_integrations RENAME TO plg_calendar_integrations;
|
|
28
|
-
END IF;
|
|
29
|
-
|
|
30
|
-
IF to_regclass('public.calendar_channels') IS NOT NULL
|
|
31
|
-
AND to_regclass('public.plg_calendar_channels') IS NULL THEN
|
|
32
|
-
ALTER TABLE public.calendar_channels RENAME TO plg_calendar_channels;
|
|
33
|
-
END IF;
|
|
34
|
-
|
|
35
|
-
IF to_regclass('public.calendar_sync_log') IS NOT NULL
|
|
36
|
-
AND to_regclass('public.plg_calendar_sync_log') IS NULL THEN
|
|
37
|
-
ALTER TABLE public.calendar_sync_log RENAME TO plg_calendar_sync_log;
|
|
38
|
-
END IF;
|
|
39
|
-
|
|
40
|
-
-- Named indexes do not follow a table rename automatically.
|
|
41
|
-
IF to_regclass('public.idx_calendar_integrations_tenant') IS NOT NULL
|
|
42
|
-
AND to_regclass('public.idx_plg_calendar_integrations_tenant') IS NULL THEN
|
|
43
|
-
ALTER INDEX public.idx_calendar_integrations_tenant RENAME TO idx_plg_calendar_integrations_tenant;
|
|
44
|
-
END IF;
|
|
45
|
-
|
|
46
|
-
IF to_regclass('public.idx_calendar_channels_tenant') IS NOT NULL
|
|
47
|
-
AND to_regclass('public.idx_plg_calendar_channels_tenant') IS NULL THEN
|
|
48
|
-
ALTER INDEX public.idx_calendar_channels_tenant RENAME TO idx_plg_calendar_channels_tenant;
|
|
49
|
-
END IF;
|
|
50
|
-
|
|
51
|
-
IF to_regclass('public.idx_calendar_channels_integration') IS NOT NULL
|
|
52
|
-
AND to_regclass('public.idx_plg_calendar_channels_integration') IS NULL THEN
|
|
53
|
-
ALTER INDEX public.idx_calendar_channels_integration RENAME TO idx_plg_calendar_channels_integration;
|
|
54
|
-
END IF;
|
|
55
|
-
END $$;
|
|
56
|
-
|
|
57
|
-
-- ===========================================================================
|
|
58
|
-
-- §2 — Re-point the inbound SECURITY DEFINER writers at the prefixed names.
|
|
59
|
-
-- These bodies are byte-identical to 002_smart_sync.sql except the calendar_*
|
|
60
|
-
-- table references, which now read plg_calendar_*. gcal_apply_event_patch and
|
|
61
|
-
-- gcal_stamp_outbound only touch public.appointments (unaffected by the rename)
|
|
62
|
-
-- and are re-asserted here for completeness so all four writers stay in step.
|
|
63
|
-
-- ===========================================================================
|
|
64
|
-
|
|
65
|
-
CREATE OR REPLACE FUNCTION public.gcal_import_event(
|
|
66
|
-
p_tenant_id uuid,
|
|
67
|
-
p_channel_id uuid,
|
|
68
|
-
p_event_id text,
|
|
69
|
-
p_etag text,
|
|
70
|
-
p_summary text,
|
|
71
|
-
p_starts_at timestamptz,
|
|
72
|
-
p_ends_at timestamptz,
|
|
73
|
-
p_all_day boolean,
|
|
74
|
-
p_description text DEFAULT NULL
|
|
75
|
-
) RETURNS uuid
|
|
76
|
-
LANGUAGE plpgsql SECURITY DEFINER
|
|
77
|
-
SET search_path = public
|
|
78
|
-
AS $$
|
|
79
|
-
DECLARE
|
|
80
|
-
v_ch record;
|
|
81
|
-
v_kind text;
|
|
82
|
-
v_assignee uuid;
|
|
83
|
-
v_location uuid;
|
|
84
|
-
v_ends timestamptz;
|
|
85
|
-
v_meta jsonb;
|
|
86
|
-
v_existing uuid;
|
|
87
|
-
v_appt uuid;
|
|
88
|
-
BEGIN
|
|
89
|
-
IF p_tenant_id IS NULL OR p_event_id IS NULL OR p_starts_at IS NULL THEN
|
|
90
|
-
RAISE EXCEPTION 'gcal_import_event: tenant, event id and start are required';
|
|
91
|
-
END IF;
|
|
92
|
-
|
|
93
|
-
PERFORM set_config('app.booking_origin', 'google', true);
|
|
94
|
-
|
|
95
|
-
SELECT c.import_mode, c.target_kind, c.target_id
|
|
96
|
-
INTO v_ch
|
|
97
|
-
FROM plg_calendar_channels c
|
|
98
|
-
WHERE c.id = p_channel_id AND c.tenant_id = p_tenant_id;
|
|
99
|
-
IF NOT FOUND THEN RAISE EXCEPTION 'gcal_import_event: unknown channel for tenant'; END IF;
|
|
100
|
-
|
|
101
|
-
v_kind := CASE WHEN v_ch.import_mode = 'appointment' THEN 'appointment' ELSE 'block' END;
|
|
102
|
-
v_assignee := CASE WHEN v_ch.target_kind = 'assignee' THEN v_ch.target_id ELSE NULL END;
|
|
103
|
-
v_location := CASE WHEN v_ch.target_kind = 'location' THEN v_ch.target_id ELSE NULL END;
|
|
104
|
-
|
|
105
|
-
v_ends := COALESCE(
|
|
106
|
-
p_ends_at,
|
|
107
|
-
CASE WHEN COALESCE(p_all_day, false) THEN p_starts_at + interval '1 day' ELSE p_starts_at END
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
v_meta := jsonb_build_object(
|
|
111
|
-
'syncOrigin', 'google',
|
|
112
|
-
'googleCalendarEventId', p_event_id,
|
|
113
|
-
'gcalEtag', p_etag,
|
|
114
|
-
'gcalChannelId', p_channel_id::text,
|
|
115
|
-
'allDay', COALESCE(p_all_day, false),
|
|
116
|
-
'title', p_summary,
|
|
117
|
-
'source', 'google_import'
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
SELECT b.id INTO v_existing
|
|
121
|
-
FROM appointments b
|
|
122
|
-
WHERE b.tenant_id = p_tenant_id
|
|
123
|
-
AND b.metadata->>'googleCalendarEventId' = p_event_id
|
|
124
|
-
LIMIT 1;
|
|
125
|
-
|
|
126
|
-
IF v_existing IS NOT NULL THEN
|
|
127
|
-
UPDATE appointments b
|
|
128
|
-
SET kind = v_kind,
|
|
129
|
-
assignee_id = v_assignee,
|
|
130
|
-
location_id = v_location,
|
|
131
|
-
starts_at = p_starts_at,
|
|
132
|
-
ends_at = v_ends,
|
|
133
|
-
status = 'scheduled',
|
|
134
|
-
notes = COALESCE(p_description, p_summary),
|
|
135
|
-
metadata = COALESCE(b.metadata, '{}'::jsonb) || v_meta,
|
|
136
|
-
updated_at = now()
|
|
137
|
-
WHERE b.id = v_existing
|
|
138
|
-
RETURNING b.id INTO v_appt;
|
|
139
|
-
ELSE
|
|
140
|
-
INSERT INTO appointments (tenant_id, kind, assignee_id, location_id,
|
|
141
|
-
starts_at, ends_at, status, notes, metadata)
|
|
142
|
-
VALUES (p_tenant_id, v_kind, v_assignee, v_location,
|
|
143
|
-
p_starts_at, v_ends, 'scheduled', COALESCE(p_description, p_summary), v_meta)
|
|
144
|
-
RETURNING id INTO v_appt;
|
|
145
|
-
END IF;
|
|
146
|
-
|
|
147
|
-
RETURN v_appt;
|
|
148
|
-
END $$;
|
|
149
|
-
|
|
150
|
-
CREATE OR REPLACE FUNCTION public.gcal_apply_event_patch(
|
|
151
|
-
p_tenant_id uuid,
|
|
152
|
-
p_event_id text,
|
|
153
|
-
p_etag text,
|
|
154
|
-
p_starts_at timestamptz,
|
|
155
|
-
p_ends_at timestamptz,
|
|
156
|
-
p_summary text,
|
|
157
|
-
p_cancelled boolean
|
|
158
|
-
) RETURNS uuid
|
|
159
|
-
LANGUAGE plpgsql SECURITY DEFINER
|
|
160
|
-
SET search_path = public
|
|
161
|
-
AS $$
|
|
162
|
-
DECLARE
|
|
163
|
-
v_appt uuid;
|
|
164
|
-
v_curr_etag text;
|
|
165
|
-
BEGIN
|
|
166
|
-
IF p_tenant_id IS NULL OR p_event_id IS NULL THEN
|
|
167
|
-
RAISE EXCEPTION 'gcal_apply_event_patch: tenant and event id are required';
|
|
168
|
-
END IF;
|
|
169
|
-
|
|
170
|
-
PERFORM set_config('app.booking_origin', 'google', true);
|
|
171
|
-
|
|
172
|
-
SELECT b.id, b.metadata->>'gcalEtag'
|
|
173
|
-
INTO v_appt, v_curr_etag
|
|
174
|
-
FROM appointments b
|
|
175
|
-
WHERE b.tenant_id = p_tenant_id
|
|
176
|
-
AND b.metadata->>'googleCalendarEventId' = p_event_id
|
|
177
|
-
LIMIT 1;
|
|
178
|
-
|
|
179
|
-
IF v_appt IS NULL THEN RETURN NULL; END IF;
|
|
180
|
-
IF p_etag IS NOT NULL AND p_etag = v_curr_etag THEN
|
|
181
|
-
RETURN NULL;
|
|
182
|
-
END IF;
|
|
183
|
-
|
|
184
|
-
IF COALESCE(p_cancelled, false) THEN
|
|
185
|
-
UPDATE appointments b
|
|
186
|
-
SET status = 'cancelled',
|
|
187
|
-
metadata = COALESCE(b.metadata, '{}'::jsonb)
|
|
188
|
-
|| jsonb_build_object('syncOrigin', 'google', 'gcalEtag', p_etag),
|
|
189
|
-
updated_at = now()
|
|
190
|
-
WHERE b.id = v_appt;
|
|
191
|
-
ELSE
|
|
192
|
-
UPDATE appointments b
|
|
193
|
-
SET starts_at = COALESCE(p_starts_at, b.starts_at),
|
|
194
|
-
ends_at = COALESCE(p_ends_at, b.ends_at),
|
|
195
|
-
notes = COALESCE(p_summary, b.notes),
|
|
196
|
-
metadata = COALESCE(b.metadata, '{}'::jsonb)
|
|
197
|
-
|| jsonb_build_object('syncOrigin', 'google',
|
|
198
|
-
'gcalEtag', p_etag,
|
|
199
|
-
'title', COALESCE(p_summary, b.metadata->>'title')),
|
|
200
|
-
updated_at = now()
|
|
201
|
-
WHERE b.id = v_appt;
|
|
202
|
-
END IF;
|
|
203
|
-
|
|
204
|
-
RETURN v_appt;
|
|
205
|
-
END $$;
|
|
206
|
-
|
|
207
|
-
CREATE OR REPLACE FUNCTION public.gcal_stamp_outbound(
|
|
208
|
-
p_tenant_id uuid,
|
|
209
|
-
p_booking_id uuid,
|
|
210
|
-
p_event_id text,
|
|
211
|
-
p_etag text DEFAULT NULL,
|
|
212
|
-
p_calendar_id text DEFAULT NULL
|
|
213
|
-
) RETURNS uuid
|
|
214
|
-
LANGUAGE plpgsql SECURITY DEFINER
|
|
215
|
-
SET search_path = public
|
|
216
|
-
AS $$
|
|
217
|
-
DECLARE
|
|
218
|
-
v_id uuid;
|
|
219
|
-
BEGIN
|
|
220
|
-
IF p_tenant_id IS NULL OR p_booking_id IS NULL OR p_event_id IS NULL THEN
|
|
221
|
-
RAISE EXCEPTION 'gcal_stamp_outbound: tenant, booking and event id are required';
|
|
222
|
-
END IF;
|
|
223
|
-
|
|
224
|
-
PERFORM set_config('app.booking_origin', 'google', true);
|
|
225
|
-
|
|
226
|
-
UPDATE appointments b
|
|
227
|
-
SET metadata = COALESCE(b.metadata, '{}'::jsonb)
|
|
228
|
-
|| jsonb_build_object('googleCalendarEventId', p_event_id,
|
|
229
|
-
'gcalEtag', p_etag,
|
|
230
|
-
'gcalSyncedAt', now())
|
|
231
|
-
|| CASE WHEN p_calendar_id IS NULL THEN '{}'::jsonb
|
|
232
|
-
ELSE jsonb_build_object('gcalCalendarId', p_calendar_id) END,
|
|
233
|
-
updated_at = now()
|
|
234
|
-
WHERE b.id = p_booking_id AND b.tenant_id = p_tenant_id
|
|
235
|
-
RETURNING b.id INTO v_id;
|
|
236
|
-
RETURN v_id;
|
|
237
|
-
END $$;
|
|
238
|
-
|
|
239
|
-
CREATE OR REPLACE FUNCTION public.gcal_unlink_channel(
|
|
240
|
-
p_channel_id uuid
|
|
241
|
-
) RETURNS uuid
|
|
242
|
-
LANGUAGE plpgsql SECURITY DEFINER
|
|
243
|
-
SET search_path = public
|
|
244
|
-
AS $$
|
|
245
|
-
DECLARE
|
|
246
|
-
v_id uuid;
|
|
247
|
-
BEGIN
|
|
248
|
-
UPDATE plg_calendar_channels c
|
|
249
|
-
SET sync_token = NULL,
|
|
250
|
-
channel_id = NULL,
|
|
251
|
-
resource_id = NULL,
|
|
252
|
-
channel_expires_at = NULL,
|
|
253
|
-
updated_at = now()
|
|
254
|
-
WHERE c.id = p_channel_id
|
|
255
|
-
RETURNING c.id INTO v_id;
|
|
256
|
-
RETURN v_id;
|
|
257
|
-
END $$;
|
|
258
|
-
|
|
259
|
-
-- Re-assert the service_role-only lock (idempotent; matches 002 §4).
|
|
260
|
-
DO $$
|
|
261
|
-
DECLARE fn text;
|
|
262
|
-
BEGIN
|
|
263
|
-
FOR fn IN SELECT unnest(ARRAY[
|
|
264
|
-
'public.gcal_import_event(uuid, uuid, text, text, text, timestamptz, timestamptz, boolean, text)',
|
|
265
|
-
'public.gcal_apply_event_patch(uuid, text, text, timestamptz, timestamptz, text, boolean)',
|
|
266
|
-
'public.gcal_stamp_outbound(uuid, uuid, text, text, text)',
|
|
267
|
-
'public.gcal_unlink_channel(uuid)'
|
|
268
|
-
])
|
|
269
|
-
LOOP
|
|
270
|
-
EXECUTE format('REVOKE ALL ON FUNCTION %s FROM public, anon, authenticated', fn);
|
|
271
|
-
EXECUTE format('GRANT EXECUTE ON FUNCTION %s TO service_role', fn);
|
|
272
|
-
END LOOP;
|
|
273
|
-
END $$;
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
// Google Calendar integration — shared types.
|
|
2
|
-
|
|
3
|
-
export interface CalendarIntegration {
|
|
4
|
-
id: string
|
|
5
|
-
provider: string
|
|
6
|
-
calendarId: string
|
|
7
|
-
active: boolean
|
|
8
|
-
connected: boolean
|
|
9
|
-
lastSyncAt?: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface CalendarSyncLogEntry {
|
|
13
|
-
id: string
|
|
14
|
-
direction: string
|
|
15
|
-
trigger?: string
|
|
16
|
-
status: string
|
|
17
|
-
fetched: number
|
|
18
|
-
written: number
|
|
19
|
-
error?: string
|
|
20
|
-
createdAt: string
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** Minimal Google Calendar event shape we read/write (subset of the API). */
|
|
24
|
-
export interface GCalEvent {
|
|
25
|
-
id: string
|
|
26
|
-
etag?: string
|
|
27
|
-
summary?: string
|
|
28
|
-
description?: string
|
|
29
|
-
/** Timed events carry dateTime; all-day events carry only `date` (YYYY-MM-DD). */
|
|
30
|
-
start: { dateTime?: string; date?: string; timeZone?: string }
|
|
31
|
-
end: { dateTime?: string; date?: string; timeZone?: string }
|
|
32
|
-
status?: string
|
|
33
|
-
/** Set on instances expanded from a recurring series (singleEvents=true). */
|
|
34
|
-
recurringEventId?: string
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Smart-sync: multi-calendar channels + wizard preview shapes
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
|
|
41
|
-
/** How a channel maps a Google calendar onto the agenda (de-para direction). */
|
|
42
|
-
export type ChannelDirection = 'inbound' | 'outbound' | 'bidirectional' | 'off'
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* What the channel targets on the Fayz side. `null` (target_kind) means the
|
|
46
|
-
* whole agenda; otherwise imports/exports scope to one assignee/service/location.
|
|
47
|
-
*/
|
|
48
|
-
export type ChannelTargetKind = 'assignee' | 'service' | 'location' | null
|
|
49
|
-
|
|
50
|
-
/** How inbound events materialize as appointments. */
|
|
51
|
-
export type ChannelImportMode = 'block' | 'appointment'
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* A per-calendar sync channel (row of public.plg_calendar_channels). One Google
|
|
55
|
-
* calendar ↔ one agenda target, with its own direction + incremental cursor.
|
|
56
|
-
*/
|
|
57
|
-
export interface CalendarChannel {
|
|
58
|
-
id: string
|
|
59
|
-
integrationId: string
|
|
60
|
-
tenantId: string
|
|
61
|
-
googleCalendarId: string
|
|
62
|
-
summary: string | null
|
|
63
|
-
color: string | null
|
|
64
|
-
direction: ChannelDirection
|
|
65
|
-
targetKind: ChannelTargetKind
|
|
66
|
-
targetId: string | null
|
|
67
|
-
importMode: ChannelImportMode
|
|
68
|
-
syncToken: string | null
|
|
69
|
-
channelId: string | null
|
|
70
|
-
resourceId: string | null
|
|
71
|
-
channelExpiresAt: string | null
|
|
72
|
-
isActive: boolean
|
|
73
|
-
createdAt: string
|
|
74
|
-
updatedAt: string
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** A future Google event not yet linked to an appointment — shown in the import wizard. */
|
|
78
|
-
export interface ExternalEventPreview {
|
|
79
|
-
eventId: string
|
|
80
|
-
etag: string
|
|
81
|
-
summary: string
|
|
82
|
-
startsAt: string
|
|
83
|
-
endsAt: string
|
|
84
|
-
allDay: boolean
|
|
85
|
-
calendarId: string
|
|
86
|
-
channelId: string
|
|
87
|
-
recurring?: boolean
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** One entry from the Google calendarList (for the de-para picker). */
|
|
91
|
-
export interface GoogleCalendarListEntry {
|
|
92
|
-
id: string
|
|
93
|
-
summary: string
|
|
94
|
-
backgroundColor?: string
|
|
95
|
-
primary?: boolean
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/** Result of an import_events run (per-item outcome tally). */
|
|
99
|
-
export interface ImportEventsResult {
|
|
100
|
-
imported: number
|
|
101
|
-
skipped: number
|
|
102
|
-
errors: { eventId: string; error: string }[]
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Raw shape of a public.appointments row as the edge function / RPCs see it
|
|
107
|
-
* (snake_case DB columns). Kept here so the pure mapping helpers can be shared
|
|
108
|
-
* between the SDK client and the Deno edge function without a DB roundtrip type.
|
|
109
|
-
*/
|
|
110
|
-
export interface AppointmentRow {
|
|
111
|
-
id: string
|
|
112
|
-
tenant_id: string
|
|
113
|
-
kind?: string | null
|
|
114
|
-
assignee_id?: string | null
|
|
115
|
-
location_id?: string | null
|
|
116
|
-
starts_at: string
|
|
117
|
-
ends_at?: string | null
|
|
118
|
-
status?: string | null
|
|
119
|
-
notes?: string | null
|
|
120
|
-
metadata?: Record<string, any> | null
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/** Raw shape of a public.plg_calendar_channels row (snake_case DB columns). */
|
|
124
|
-
export interface CalendarChannelRow {
|
|
125
|
-
id: string
|
|
126
|
-
integration_id: string
|
|
127
|
-
tenant_id: string
|
|
128
|
-
google_calendar_id: string
|
|
129
|
-
summary?: string | null
|
|
130
|
-
color?: string | null
|
|
131
|
-
direction: ChannelDirection
|
|
132
|
-
target_kind?: ChannelTargetKind
|
|
133
|
-
target_id?: string | null
|
|
134
|
-
import_mode?: ChannelImportMode
|
|
135
|
-
sync_token?: string | null
|
|
136
|
-
channel_id?: string | null
|
|
137
|
-
resource_id?: string | null
|
|
138
|
-
channel_expires_at?: string | null
|
|
139
|
-
is_active?: boolean | null
|
|
140
|
-
created_at?: string
|
|
141
|
-
updated_at?: string
|
|
142
|
-
}
|
package/src/lib/tenant.ts
DELETED
package/src/locales/en.ts
DELETED
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
// agenda.* — merged plugin-own + saas-core central i18n
|
|
2
|
-
export const en: Record<string, string> = {
|
|
3
|
-
"agenda.appointment.addDescription": "Add description...",
|
|
4
|
-
"agenda.appointment.addService": "Add service",
|
|
5
|
-
"agenda.appointment.cancel": "Cancel",
|
|
6
|
-
"agenda.appointment.clientTab": "Client",
|
|
7
|
-
"agenda.appointment.noClientData": "No client data available",
|
|
8
|
-
"agenda.appointment.client": "Client",
|
|
9
|
-
"agenda.appointment.conflict": "Time conflict — this professional is already booked at this time.",
|
|
10
|
-
"agenda.appointment.create": "Create",
|
|
11
|
-
"agenda.appointment.createClientFailed": "Failed to create client",
|
|
12
|
-
"agenda.appointment.creating": "Creating...",
|
|
13
|
-
"agenda.appointment.delete": "Delete",
|
|
14
|
-
"agenda.appointment.deleteConfirm": "Delete this appointment?",
|
|
15
|
-
"agenda.appointment.confirmDelete": "Delete",
|
|
16
|
-
"agenda.appointment.deleting": "Deleting…",
|
|
17
|
-
"agenda.appointment.edit": "Edit Appointment",
|
|
18
|
-
"agenda.appointment.emailOptional": "Email (optional)",
|
|
19
|
-
"agenda.appointment.location": "Location",
|
|
20
|
-
"agenda.appointment.name": "Name",
|
|
21
|
-
"agenda.appointment.new": "New Appointment",
|
|
22
|
-
"agenda.appointment.newClient": "New client",
|
|
23
|
-
"agenda.appointment.notes": "Notes",
|
|
24
|
-
"agenda.appointment.phone": "Phone",
|
|
25
|
-
"agenda.appointment.professional": "Professional",
|
|
26
|
-
"agenda.appointment.save": "Save",
|
|
27
|
-
"agenda.appointment.saving": "Saving...",
|
|
28
|
-
"agenda.appointment.searchClient": "Search client...",
|
|
29
|
-
"agenda.appointment.searchService": "Search service to add...",
|
|
30
|
-
"agenda.appointment.selectLocation": "Select location...",
|
|
31
|
-
"agenda.appointment.selectProfessional": "Select professional...",
|
|
32
|
-
"agenda.appointment.selectClientHint": "Select the client from the list or use New client to enable saving.",
|
|
33
|
-
"agenda.appointment.services": "Services",
|
|
34
|
-
"agenda.appointment.status": "Status",
|
|
35
|
-
"agenda.appointment.to": "to",
|
|
36
|
-
"agenda.appointment.total": "Total",
|
|
37
|
-
"agenda.appointment.update": "Update",
|
|
38
|
-
"agenda.payment.title": "Payment",
|
|
39
|
-
"agenda.payment.generateInvoice": "Generate invoice",
|
|
40
|
-
"agenda.payment.generating": "Generating…",
|
|
41
|
-
"agenda.payment.pending": "Pending",
|
|
42
|
-
"agenda.payment.partial": "Partial",
|
|
43
|
-
"agenda.payment.paid": "Paid",
|
|
44
|
-
"agenda.payment.collect": "Collect",
|
|
45
|
-
"agenda.payment.overdue": "Overdue",
|
|
46
|
-
"agenda.payment.cancelled": "Cancelled",
|
|
47
|
-
"agenda.payment.none": "Payment",
|
|
48
|
-
"agenda.payment.pay": "Pay",
|
|
49
|
-
"agenda.payment.paying": "Paying…",
|
|
50
|
-
"agenda.payment.remaining": "Remaining",
|
|
51
|
-
"agenda.payment.installment": "Installment",
|
|
52
|
-
"agenda.payment.total": "Total",
|
|
53
|
-
"agenda.payment.noInvoice": "No invoice generated",
|
|
54
|
-
"agenda.payment.selectAccount": "Select account",
|
|
55
|
-
"agenda.payment.registerPayment": "Register payment",
|
|
56
|
-
"agenda.payment.registerPaymentHint": "Record a payment for this appointment",
|
|
57
|
-
"agenda.payment.pendingHint": "Invoice generated, awaiting payment",
|
|
58
|
-
"agenda.payment.partialHint": "Partially paid, tap to complete",
|
|
59
|
-
"agenda.payment.paidHint": "Payment completed",
|
|
60
|
-
"agenda.payment.overdueHint": "Payment overdue",
|
|
61
|
-
"agenda.payment.backToAppointment": "Back to appointment",
|
|
62
|
-
"agenda.payment.checkout": "Confirm",
|
|
63
|
-
"agenda.payment.checkingOut": "Processing…",
|
|
64
|
-
"agenda.payment.serviceSummary": "Service summary",
|
|
65
|
-
"agenda.payment.paymentMethod": "Payment method",
|
|
66
|
-
"agenda.payment.noMethods": "No payment methods configured.",
|
|
67
|
-
"agenda.payment.configureMethods": "Set up payment methods",
|
|
68
|
-
"agenda.payment.checkoutComplete": "Payment confirmed",
|
|
69
|
-
"agenda.payment.card": "Card",
|
|
70
|
-
"agenda.payment.method": "Method",
|
|
71
|
-
"agenda.payment.select": "Select…",
|
|
72
|
-
"agenda.payment.cardBrand": "Brand",
|
|
73
|
-
"agenda.payment.selectBrand": "Select brand…",
|
|
74
|
-
"agenda.payment.cardInstallments": "Installments",
|
|
75
|
-
"agenda.payment.bankAccount": "Account",
|
|
76
|
-
"agenda.payment.viewInvoice": "View invoice details",
|
|
77
|
-
"agenda.calendar.agendas": "Agendas",
|
|
78
|
-
"agenda.calendar.create": "Create",
|
|
79
|
-
"agenda.calendar.next": "Next",
|
|
80
|
-
"agenda.calendar.previous": "Previous",
|
|
81
|
-
"agenda.calendar.status": "Status",
|
|
82
|
-
"agenda.calendar.today": "Today",
|
|
83
|
-
"agenda.calendar.viewAgenda": "Agenda",
|
|
84
|
-
"agenda.calendar.viewDay": "Day",
|
|
85
|
-
"agenda.calendar.viewList": "List",
|
|
86
|
-
"agenda.calendar.viewMonth": "Month",
|
|
87
|
-
"agenda.calendar.viewWeek": "Week",
|
|
88
|
-
"agenda.list.today": "Today",
|
|
89
|
-
"agenda.list.tomorrow": "Tomorrow",
|
|
90
|
-
"agenda.list.empty": "No upcoming items",
|
|
91
|
-
"agenda.confirmations.confirmed": "Confirmed:",
|
|
92
|
-
"agenda.confirmations.empty": "No pending confirmations",
|
|
93
|
-
"agenda.confirmations.emptySubtitle": "All upcoming appointments have been confirmed",
|
|
94
|
-
"agenda.confirmations.loading": "Loading...",
|
|
95
|
-
"agenda.confirmations.subtitle": "Upcoming appointments pending confirmation",
|
|
96
|
-
"agenda.confirmations.unknownClient": "Unknown client",
|
|
97
|
-
"agenda.confirmations.sendWhatsApp": "Send WhatsApp",
|
|
98
|
-
"agenda.confirmations.call": "Call",
|
|
99
|
-
"agenda.confirmations.markConfirmed": "Mark Confirmed",
|
|
100
|
-
"agenda.confirmations.markCancelled": "Mark Cancelled",
|
|
101
|
-
"agenda.cancellation.loadingReasons": "Loading reasons...",
|
|
102
|
-
"agenda.cancellation.notesOptional": "Cancellation notes (optional)",
|
|
103
|
-
"agenda.cancellation.notesRequired": "Cancellation notes required",
|
|
104
|
-
"agenda.cancellation.selectReason": "Select cancellation reason",
|
|
105
|
-
"agenda.contextMenu.changeStatus": "Change status",
|
|
106
|
-
"agenda.contextMenu.delete": "Delete",
|
|
107
|
-
"agenda.contextMenu.edit": "Edit",
|
|
108
|
-
"agenda.contextMenu.notAvailable": "(not available)",
|
|
109
|
-
"agenda.index.settingsSubtitle": "Working hours, scheduling preferences, and confirmations",
|
|
110
|
-
"agenda.index.settingsTitle": "Agenda Settings",
|
|
111
|
-
"settings.plugin.agenda-working-hours": "Working Hours",
|
|
112
|
-
"agenda.popover.unknown": "Unknown",
|
|
113
|
-
"agenda.settings.autoConfirm": "Auto-confirm",
|
|
114
|
-
"agenda.settings.autoConfirmDesc": "Automatically confirm new bookings",
|
|
115
|
-
"agenda.settings.autoCreateOrder": "Auto-create Order",
|
|
116
|
-
"agenda.settings.autoCreateOrderDesc": "Automatically create a financial order for new bookings",
|
|
117
|
-
"agenda.settings.blockOutside": "Block Outside Hours",
|
|
118
|
-
"agenda.settings.blockOutsideDesc": "Prevent bookings outside working hours",
|
|
119
|
-
"agenda.settings.calendarDisplay": "Calendar Display",
|
|
120
|
-
"agenda.settings.calendarDisplayDesc": "Visual settings for the calendar",
|
|
121
|
-
"agenda.settings.cancelAlerts": "Cancellation Alerts",
|
|
122
|
-
"agenda.settings.cancelAlertsDesc": "Notify when a booking is cancelled",
|
|
123
|
-
"agenda.settings.compact": "Compact Mode",
|
|
124
|
-
"agenda.settings.compactDesc": "Use smaller event blocks",
|
|
125
|
-
"agenda.settings.confirmations": "Confirmations",
|
|
126
|
-
"agenda.settings.confirmationsDesc": "Booking confirmation settings",
|
|
127
|
-
"agenda.settings.conflictDetection": "Conflict Detection",
|
|
128
|
-
"agenda.settings.conflictDetectionDesc": "Warn when bookings overlap",
|
|
129
|
-
"agenda.settings.dragDrop": "Drag & Drop",
|
|
130
|
-
"agenda.settings.dragDropDesc": "Allow rescheduling by dragging events",
|
|
131
|
-
"agenda.settings.enableConfirmations": "Enable Confirmations",
|
|
132
|
-
"agenda.settings.enableConfirmationsDesc": "Require confirmation for new bookings",
|
|
133
|
-
"agenda.settings.enableLocation": "Enable Location Selection",
|
|
134
|
-
"agenda.settings.enableLocationDesc": "Show location picker in booking modal",
|
|
135
|
-
"agenda.settings.enableWorkingHours": "Enable Working Hours",
|
|
136
|
-
"agenda.settings.enableWorkingHoursDesc": "Show working hours overlay on calendar",
|
|
137
|
-
"agenda.settings.locations": "Locations",
|
|
138
|
-
"agenda.settings.locationsDesc": "Multi-location settings",
|
|
139
|
-
"agenda.settings.newBookingNotif": "New Booking Alerts",
|
|
140
|
-
"agenda.settings.newBookingNotifDesc": "Notify when a new booking is created",
|
|
141
|
-
"agenda.settings.noShowTracking": "No-show Tracking",
|
|
142
|
-
"agenda.settings.noShowTrackingDesc": "Track and alert on no-shows",
|
|
143
|
-
"agenda.settings.notifications": "Notifications",
|
|
144
|
-
"agenda.settings.notificationsDesc": "Notification preferences",
|
|
145
|
-
"agenda.settings.reminder": "Reminders",
|
|
146
|
-
"agenda.settings.reminderDesc": "Send reminders before appointments",
|
|
147
|
-
"agenda.settings.scheduling": "Scheduling",
|
|
148
|
-
"agenda.settings.schedulingDesc": "Configure scheduling behavior",
|
|
149
|
-
"agenda.settings.showCancelled": "Show Cancelled",
|
|
150
|
-
"agenda.settings.showCancelledDesc": "Display cancelled bookings on calendar",
|
|
151
|
-
"agenda.settings.showNoShow": "Show No-shows",
|
|
152
|
-
"agenda.settings.showNoShowDesc": "Display no-show bookings on calendar",
|
|
153
|
-
"agenda.settings.workingHours": "Working Hours",
|
|
154
|
-
"agenda.settings.workingHoursDesc": "Working hours and availability",
|
|
155
|
-
"agenda.sidebar.agendas": "Agendas",
|
|
156
|
-
"agenda.sidebar.allLocations": "All locations",
|
|
157
|
-
"agenda.sidebar.create": "Create",
|
|
158
|
-
"agenda.sidebar.location": "Location",
|
|
159
|
-
"agenda.sidebar.status": "Status",
|
|
160
|
-
"agenda.toolbar.next": "Next",
|
|
161
|
-
"agenda.toolbar.previous": "Previous",
|
|
162
|
-
"agenda.toolbar.today": "Today",
|
|
163
|
-
"agenda.workingHours.addBreak": "Add break",
|
|
164
|
-
"agenda.workingHours.copyToAll": "Copy to all",
|
|
165
|
-
"agenda.workingHours.dayOff": "Day off",
|
|
166
|
-
"agenda.workingHours.removePeriod": "Remove period",
|
|
167
|
-
"agenda.workingHours.professional": "Professional",
|
|
168
|
-
"agenda.workingHours.save": "Save",
|
|
169
|
-
"agenda.workingHours.saveFailed": "Failed to save",
|
|
170
|
-
"agenda.workingHours.saved": "Working hours saved",
|
|
171
|
-
"agenda.workingHours.saving": "Saving...",
|
|
172
|
-
"agenda.workingHours.subtitle": "Manage working hours per professional",
|
|
173
|
-
"agenda.workingHours.to": "to",
|
|
174
|
-
"agenda.title": "Agenda",
|
|
175
|
-
"agenda.calendar.title": "Calendar",
|
|
176
|
-
"agenda.calendar.noScheduleConfirm": "This time slot has no open schedule for this professional. Do you want to book anyway?",
|
|
177
|
-
"agenda.calendar.newAppointment": "New Appointment",
|
|
178
|
-
"agenda.booking.create": "New Appointment",
|
|
179
|
-
"agenda.booking.edit": "Edit Appointment",
|
|
180
|
-
"agenda.booking.delete": "Delete Appointment",
|
|
181
|
-
"agenda.booking.deleteConfirm": "Are you sure you want to delete this appointment?",
|
|
182
|
-
"agenda.booking.client": "Client",
|
|
183
|
-
"agenda.booking.professional": "Professional",
|
|
184
|
-
"agenda.booking.services": "Services",
|
|
185
|
-
"agenda.booking.date": "Date",
|
|
186
|
-
"agenda.booking.time": "Time",
|
|
187
|
-
"agenda.booking.duration": "Duration",
|
|
188
|
-
"agenda.booking.notes": "Notes",
|
|
189
|
-
"agenda.booking.status": "Status",
|
|
190
|
-
"agenda.booking.save": "Save Appointment",
|
|
191
|
-
"agenda.booking.saving": "Saving...",
|
|
192
|
-
"agenda.confirmations.title": "Confirmations",
|
|
193
|
-
"agenda.confirmations.pending": "Pending Confirmations",
|
|
194
|
-
"agenda.confirmations.emptyDescription": "All upcoming appointments have been confirmed",
|
|
195
|
-
"agenda.confirmations.confirm": "Confirm",
|
|
196
|
-
"agenda.confirmations.cancel": "Cancel",
|
|
197
|
-
"agenda.workingHours.title": "Working Hours",
|
|
198
|
-
"agenda.workingHours.addPeriod": "Add period",
|
|
199
|
-
"agenda.workingHours.loading": "Loading...",
|
|
200
|
-
"agenda.appointment.addClient": "Add client",
|
|
201
|
-
"agenda.appointment.addServiceFirst": "Add service",
|
|
202
|
-
"agenda.appointment.addNotes": "Add notes",
|
|
203
|
-
"agenda.appointment.duration": "Duration (minutes)",
|
|
204
|
-
"agenda.appointment.price": "Price",
|
|
205
|
-
"agenda.appointment.title": "Title",
|
|
206
|
-
"agenda.appointment.addTitle": "Add a title",
|
|
207
|
-
"agenda.appointment.untitled": "(no title)",
|
|
208
|
-
"agenda.bookingType.appointment": "Appointment",
|
|
209
|
-
"agenda.bookingType.event": "Event",
|
|
210
|
-
"agenda.bookingType.task": "Task",
|
|
211
|
-
"agenda.bookingType.out_of_office": "Out of Office",
|
|
212
|
-
"agenda.bookingType.block": "Block",
|
|
213
|
-
"agenda.settings.title": "Agenda Settings",
|
|
214
|
-
"agenda.settings.slotDuration": "Slot Duration",
|
|
215
|
-
"agenda.settings.bookingKind": "Booking Kind",
|
|
216
|
-
"agenda.settings.dayStartTime": "Day Start Time",
|
|
217
|
-
"agenda.settings.dayStartTimeDesc": "First hour shown on the calendar",
|
|
218
|
-
"agenda.settings.dayEndTime": "Day End Time",
|
|
219
|
-
"agenda.settings.dayEndTimeDesc": "Last hour shown on the calendar",
|
|
220
|
-
}
|