From aa36bc665618ebd72367288d7bdbc7ab75a27b5a Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Thu, 23 Oct 2025 11:54:45 +0200 Subject: [PATCH] Huge bump with turborepo --- .gitignore | 4 + README.md | 172 + apps/external/biome.json | 342 ++ {ui => apps}/external/index.html | 3 +- apps/external/package.json | 41 + {ui => apps/external}/public/icon.jpg | Bin {ui => apps/external}/public/logo_dark.png | Bin {ui => apps/external}/public/logo_white.png | Bin {ui => apps/external}/public/staging_icon.jpg | Bin {ui => apps/external}/public/vite.svg | 0 .../external/src}/CustomModal.tsx | 4 +- .../external/src}/EmbeddedBookingPage.tsx | 67 +- .../external/src}/FloatingBookingWidget.tsx | 56 +- .../external/src}/LoadingSpinner.tsx | 0 apps/external/src/UserStoreProvider.tsx | 97 + apps/external/src/lib/api.ts | 3 + apps/external/src/lib/supabase.ts | 10 + {ui => apps/external}/src/main.css | 0 .../external => apps/external/src}/main.tsx | 21 +- apps/external/src/routes.tsx | 12 + {ui => apps/external}/src/vite-env.d.ts | 0 .../external/tsconfig.json | 23 +- apps/external/vite.config.ts | 26 + {ui => apps/main}/.env.production | 0 {ui => apps/main}/.env.staging | 0 apps/main/biome.json | 342 ++ apps/main/index.html | 13 + {ui => apps/main}/package.json | 23 +- {ui/src/assets => apps/main/public}/icon.jpg | Bin .../main/public/logo_dark.png | Bin apps/main/public/logo_white.png | Bin 0 -> 4562 bytes .../main/public}/staging_icon.jpg | Bin apps/main/public/vite.svg | 1 + {ui => apps/main}/src/App.tsx | 15 +- {ui => apps/main}/src/assets/google.png | Bin apps/main/src/assets/icon.jpg | Bin 0 -> 43486 bytes apps/main/src/assets/icon.png | Bin 0 -> 85535 bytes {ui => apps/main}/src/assets/react.svg | 0 apps/main/src/assets/staging_icon.jpg | Bin 0 -> 53834 bytes .../src/components/AnimatedBackground.tsx | 0 .../src/components/AuthenticationGateway.tsx | 2 +- .../components/AuthenticationGateway.unit.tsx | 21 +- .../main}/src/components/AvailabilityCard.tsx | 8 +- .../components/AvailabilityVisualization.tsx | 14 +- .../BrandButtons/LoginWithGoogle.test.tsx | 2 +- .../BrandButtons/LoginWithGoogle.tsx | 0 .../BrandButtons/login-with-google.css | 0 .../main}/src/components/ChannelBadge.tsx | 2 +- .../main}/src/components/ChannelPreview.tsx | 8 +- .../main}/src/components/ClickOutside.md | 0 .../main}/src/components/ClickOutside.tsx | 2 +- .../main}/src/components/CreateTabloModal.tsx | 2 +- .../src/components/CustomChannelHeader.tsx | 2 +- .../src/components/CustomLoadingOverlay.tsx | 0 apps/main/src/components/CustomModal.tsx | 45 + .../main}/src/components/DeleteTabloModal.tsx | 2 +- .../main}/src/components/EmbedConfigModal.tsx | 39 +- .../src/components/EventDetailsModal.tsx | 6 +- .../main}/src/components/EventModal.tsx | 24 +- .../main}/src/components/EventTypeCard.tsx | 43 +- .../main}/src/components/EventTypeModal.tsx | 16 +- .../main}/src/components/ExceptionModal.tsx | 16 +- .../main}/src/components/ImageColorPicker.tsx | 0 .../main}/src/components/ImageCropDialog.tsx | 8 +- .../main}/src/components/ImportICSModal.tsx | 18 +- .../main}/src/components/Layout.test.tsx | 8 +- {ui => apps/main}/src/components/Layout.tsx | 2 +- apps/main/src/components/LoadingSpinner.tsx | 12 + .../src/components/NavigationBar.test.tsx | 2 +- .../main}/src/components/NavigationBar.tsx | 57 +- .../src/components/ProtectedRoute.test.tsx | 6 +- .../main}/src/components/ProtectedRoute.tsx | 4 +- .../main}/src/components/StatusPicker.tsx | 0 .../main}/src/components/TabloModal.tsx | 22 +- .../main}/src/components/TabloTutorial.tsx | 2 +- .../src/components/ThemeSwitcher.test.tsx | 2 +- .../main}/src/components/ThemeSwitcher.tsx | 6 +- .../main}/src/components/WebcalModal.tsx | 26 +- {ui => apps/main}/src/components/header.tsx | 4 +- {ui => apps/main}/src/hooks/auth.ts | 127 +- {ui => apps/main}/src/hooks/availabilities.ts | 21 +- {ui => apps/main}/src/hooks/channel.ts | 0 {ui => apps/main}/src/hooks/devis.ts | 11 +- {ui => apps/main}/src/hooks/event-types.ts | 24 +- {ui => apps/main}/src/hooks/events.ts | 23 +- {ui => apps/main}/src/hooks/feedback.ts | 6 +- {ui => apps/main}/src/hooks/intros.ts | 10 +- {ui => apps/main}/src/hooks/invite.ts | 35 +- {ui => apps/main}/src/hooks/profile.ts | 28 +- {ui => apps/main}/src/hooks/tablo_data.ts | 89 +- {ui => apps/main}/src/hooks/tablos.ts | 132 +- {ui => apps/main}/src/hooks/user.ts | 2 +- {ui => apps/main}/src/hooks/webcal.ts | 22 +- apps/main/src/lib/api.ts | 3 + apps/main/src/lib/env.ts | 4 + {ui => apps/main}/src/lib/routes.tsx | 44 +- {ui => apps/main}/src/lib/rum.ts | 0 apps/main/src/lib/supabase.ts | 10 + apps/main/src/main.css | 1271 +++++ {ui => apps/main}/src/main.tsx | 3 +- {ui => apps/main}/src/pages/NotFoundPage.tsx | 2 +- .../main}/src/pages/PublicBookingPage.tsx | 49 +- .../main}/src/pages/availabilities.tsx | 24 +- {ui => apps/main}/src/pages/bookings.tsx | 18 +- {ui => apps/main}/src/pages/chantiers.tsx | 0 {ui => apps/main}/src/pages/chat.tsx | 6 +- .../main}/src/pages/event-types-page.tsx | 10 +- {ui => apps/main}/src/pages/factures.tsx | 0 {ui => apps/main}/src/pages/feedback.tsx | 14 +- {ui => apps/main}/src/pages/join.tsx | 10 +- {ui => apps/main}/src/pages/landing.tsx | 7 +- {ui => apps/main}/src/pages/login.tsx | 20 +- {ui => apps/main}/src/pages/oauth-signin.tsx | 7 +- {ui => apps/main}/src/pages/planning.tsx | 20 +- .../main}/src/pages/reset-password.tsx | 12 +- {ui => apps/main}/src/pages/settings.tsx | 28 +- {ui => apps/main}/src/pages/signup.tsx | 20 +- {ui => apps/main}/src/pages/tablo.tsx | 20 +- .../main}/src/providers/ChatProvider.tsx | 0 .../src/providers/DatadogRumProvider.tsx | 6 +- .../main}/src/providers/UserStoreProvider.tsx | 9 +- {ui => apps/main}/src/setupTests.ts | 0 apps/main/src/utils/iconHelpers.ts | 7 + {ui => apps/main}/src/utils/testHelpers.tsx | 6 +- apps/main/src/vite-env.d.ts | 1 + apps/main/stats.html | 4949 +++++++++++++++++ apps/main/tsconfig.app.json | 43 + {ui => apps/main}/tsconfig.json | 0 {ui => apps/main}/tsconfig.node.json | 0 {ui => apps/main}/tsconfig.worker.json | 0 {ui => apps/main}/vite.config.d.ts | 0 apps/main/vite.config.ts | 28 + {ui => apps/main}/worker-configuration.d.ts | 1884 ++++++- apps/main/worker/index.d.ts | 4 + {ui => apps/main}/worker/index.ts | 6 +- {ui => apps/main}/wrangler.toml | 0 package.json | 27 + packages/shared/package.json | 51 + .../shared}/src/contexts/SessionContext.tsx | 11 +- .../shared}/src/contexts/ThemeContext.tsx | 0 packages/shared/src/hooks/auth.ts | 106 + {ui => packages/shared}/src/hooks/public.ts | 29 +- packages/shared/src/hooks/tablos.ts | 57 + .../shared}/src/hooks/useClickOutside.ts | 0 packages/shared/src/index.ts | 25 + {ui => packages/shared}/src/lib/api.ts | 15 +- .../utils.ts => packages/shared/src/lib/cn.ts | 0 packages/shared/src/lib/supabase.ts | 3 + {ui => packages/shared}/src/lib/toast.ts | 0 .../shared}/src/types/database.types.ts | 0 .../shared}/src/types/events.types.ts | 4 +- .../shared}/src/types/kanban.types.ts | 0 .../shared}/src/types/removeNull.ts | 0 .../shared}/src/types/tablos.types.ts | 6 +- {ui => packages/shared}/src/utils/helpers.ts | 30 +- packages/shared/tsconfig.json | 26 + packages/shared/tsconfig.tsbuildinfo | 1 + packages/ui/components.json | 20 + packages/ui/package.json | 59 + .../ui/src/components}/avatar.tsx | 2 +- .../ui/src/components}/badge.tsx | 2 +- .../ui/src/components}/button-group.tsx | 4 +- .../ui/src/components}/button.tsx | 2 +- .../ui/src/components}/calendar.tsx | 4 +- .../ui/src/components}/card.tsx | 2 +- .../ui/src/components}/checkbox.tsx | 2 +- .../ui/src/components}/clipboard.tsx | 4 +- .../ui/src/components}/collapsible.tsx | 0 .../ui/src/components}/date-field.tsx | 8 +- .../ui/src/components}/date-picker.tsx | 8 +- .../ui/src/components}/dialog.tsx | 2 +- .../ui/src/components}/dropdown-menu.tsx | 2 +- .../ui/src/components}/empty.tsx | 2 +- .../ui/src/components}/field.tsx | 6 +- packages/ui/src/components/index.ts | 29 + .../ui/src/components}/input.tsx | 2 +- .../ui/src/components}/label.tsx | 2 +- .../ui/src/components}/popover.tsx | 2 +- .../ui/src/components}/select.tsx | 2 +- .../ui/src/components}/separator.tsx | 2 +- .../ui/src/components}/slider.tsx | 2 +- .../ui/src/components}/sonner.tsx | 2 +- .../ui/src/components}/switch.tsx | 2 +- .../ui/src/components}/tabs.tsx | 2 +- .../ui/src/components}/textarea.tsx | 2 +- .../ui/src/components}/time-input.tsx | 6 +- .../ui/src/components}/tooltip.tsx | 2 +- .../ui/src/components}/typography.tsx | 2 +- .../ui/src}/hooks/use-clipboard.ts | 0 packages/ui/src/styles/globals.css | 127 + packages/ui/tsconfig.json | 33 + packages/ui/tsconfig.tsbuildinfo | 1 + ui/pnpm-lock.yaml => pnpm-lock.yaml | 1591 ++++-- pnpm-workspace.yaml | 4 + turbo.json | 28 + ui/.gitignore | 26 - ui/.wrangler/deploy/config.json | 1 - ui/README.md | 1 - ui/components.json | 22 - ui/index.html | 27 - ui/src/external/routes.tsx | 19 - ui/src/hooks/support.ts | 32 - ui/src/utils/iconHelpers.ts | 7 - ui/stats.html | 4949 ----------------- ui/vite.config.ts | 57 - ui/worker/index.d.ts | 4 - 206 files changed, 11473 insertions(+), 6818 deletions(-) create mode 100644 README.md create mode 100644 apps/external/biome.json rename {ui => apps}/external/index.html (70%) create mode 100644 apps/external/package.json rename {ui => apps/external}/public/icon.jpg (100%) rename {ui => apps/external}/public/logo_dark.png (100%) rename {ui => apps/external}/public/logo_white.png (100%) rename {ui => apps/external}/public/staging_icon.jpg (100%) rename {ui => apps/external}/public/vite.svg (100%) rename {ui/src/components => apps/external/src}/CustomModal.tsx (94%) rename {ui/src/external => apps/external/src}/EmbeddedBookingPage.tsx (95%) rename {ui/src/external => apps/external/src}/FloatingBookingWidget.tsx (94%) rename {ui/src/components => apps/external/src}/LoadingSpinner.tsx (100%) create mode 100644 apps/external/src/UserStoreProvider.tsx create mode 100644 apps/external/src/lib/api.ts create mode 100644 apps/external/src/lib/supabase.ts rename {ui => apps/external}/src/main.css (100%) rename {ui/src/external => apps/external/src}/main.tsx (53%) create mode 100644 apps/external/src/routes.tsx rename {ui => apps/external}/src/vite-env.d.ts (100%) rename ui/tsconfig.app.json => apps/external/tsconfig.json (58%) create mode 100644 apps/external/vite.config.ts rename {ui => apps/main}/.env.production (100%) rename {ui => apps/main}/.env.staging (100%) create mode 100644 apps/main/biome.json create mode 100644 apps/main/index.html rename {ui => apps/main}/package.json (91%) rename {ui/src/assets => apps/main/public}/icon.jpg (100%) rename ui/src/assets/icon.png => apps/main/public/logo_dark.png (100%) create mode 100644 apps/main/public/logo_white.png rename {ui/src/assets => apps/main/public}/staging_icon.jpg (100%) create mode 100644 apps/main/public/vite.svg rename {ui => apps/main}/src/App.tsx (67%) rename {ui => apps/main}/src/assets/google.png (100%) create mode 100644 apps/main/src/assets/icon.jpg create mode 100644 apps/main/src/assets/icon.png rename {ui => apps/main}/src/assets/react.svg (100%) create mode 100644 apps/main/src/assets/staging_icon.jpg rename {ui => apps/main}/src/components/AnimatedBackground.tsx (100%) rename {ui => apps/main}/src/components/AuthenticationGateway.tsx (94%) rename {ui => apps/main}/src/components/AuthenticationGateway.unit.tsx (78%) rename {ui => apps/main}/src/components/AvailabilityCard.tsx (97%) rename {ui => apps/main}/src/components/AvailabilityVisualization.tsx (80%) rename {ui => apps/main}/src/components/BrandButtons/LoginWithGoogle.test.tsx (95%) rename {ui => apps/main}/src/components/BrandButtons/LoginWithGoogle.tsx (100%) rename {ui => apps/main}/src/components/BrandButtons/login-with-google.css (100%) rename {ui => apps/main}/src/components/ChannelBadge.tsx (92%) rename {ui => apps/main}/src/components/ChannelPreview.tsx (95%) rename {ui => apps/main}/src/components/ClickOutside.md (100%) rename {ui => apps/main}/src/components/ClickOutside.tsx (91%) rename {ui => apps/main}/src/components/CreateTabloModal.tsx (98%) rename {ui => apps/main}/src/components/CustomChannelHeader.tsx (95%) rename {ui => apps/main}/src/components/CustomLoadingOverlay.tsx (100%) create mode 100644 apps/main/src/components/CustomModal.tsx rename {ui => apps/main}/src/components/DeleteTabloModal.tsx (98%) rename {ui => apps/main}/src/components/EmbedConfigModal.tsx (89%) rename {ui => apps/main}/src/components/EventDetailsModal.tsx (95%) rename {ui => apps/main}/src/components/EventModal.tsx (92%) rename {ui => apps/main}/src/components/EventTypeCard.tsx (79%) rename {ui => apps/main}/src/components/EventTypeModal.tsx (95%) rename {ui => apps/main}/src/components/ExceptionModal.tsx (95%) rename {ui => apps/main}/src/components/ImageColorPicker.tsx (100%) rename {ui => apps/main}/src/components/ImageCropDialog.tsx (95%) rename {ui => apps/main}/src/components/ImportICSModal.tsx (95%) rename {ui => apps/main}/src/components/Layout.test.tsx (87%) rename {ui => apps/main}/src/components/Layout.tsx (95%) create mode 100644 apps/main/src/components/LoadingSpinner.tsx rename {ui => apps/main}/src/components/NavigationBar.test.tsx (98%) rename {ui => apps/main}/src/components/NavigationBar.tsx (89%) rename {ui => apps/main}/src/components/ProtectedRoute.test.tsx (94%) rename {ui => apps/main}/src/components/ProtectedRoute.tsx (91%) rename {ui => apps/main}/src/components/StatusPicker.tsx (100%) rename {ui => apps/main}/src/components/TabloModal.tsx (98%) rename {ui => apps/main}/src/components/TabloTutorial.tsx (99%) rename {ui => apps/main}/src/components/ThemeSwitcher.test.tsx (95%) rename {ui => apps/main}/src/components/ThemeSwitcher.tsx (91%) rename {ui => apps/main}/src/components/WebcalModal.tsx (91%) rename {ui => apps/main}/src/components/header.tsx (96%) rename {ui => apps/main}/src/hooks/auth.ts (60%) rename {ui => apps/main}/src/hooks/availabilities.ts (91%) rename {ui => apps/main}/src/hooks/channel.ts (100%) rename {ui => apps/main}/src/hooks/devis.ts (88%) rename {ui => apps/main}/src/hooks/event-types.ts (89%) rename {ui => apps/main}/src/hooks/events.ts (93%) rename {ui => apps/main}/src/hooks/feedback.ts (78%) rename {ui => apps/main}/src/hooks/intros.ts (94%) rename {ui => apps/main}/src/hooks/invite.ts (54%) rename {ui => apps/main}/src/hooks/profile.ts (85%) rename {ui => apps/main}/src/hooks/tablo_data.ts (82%) rename {ui => apps/main}/src/hooks/tablos.ts (54%) rename {ui => apps/main}/src/hooks/user.ts (94%) rename {ui => apps/main}/src/hooks/webcal.ts (68%) create mode 100644 apps/main/src/lib/api.ts create mode 100644 apps/main/src/lib/env.ts rename {ui => apps/main}/src/lib/routes.tsx (72%) rename {ui => apps/main}/src/lib/rum.ts (100%) create mode 100644 apps/main/src/lib/supabase.ts create mode 100644 apps/main/src/main.css rename {ui => apps/main}/src/main.tsx (83%) rename {ui => apps/main}/src/pages/NotFoundPage.tsx (94%) rename {ui => apps/main}/src/pages/PublicBookingPage.tsx (94%) rename {ui => apps/main}/src/pages/availabilities.tsx (95%) rename {ui => apps/main}/src/pages/bookings.tsx (97%) rename {ui => apps/main}/src/pages/chantiers.tsx (100%) rename {ui => apps/main}/src/pages/chat.tsx (93%) rename {ui => apps/main}/src/pages/event-types-page.tsx (91%) rename {ui => apps/main}/src/pages/factures.tsx (100%) rename {ui => apps/main}/src/pages/feedback.tsx (92%) rename {ui => apps/main}/src/pages/join.tsx (91%) rename {ui => apps/main}/src/pages/landing.tsx (99%) rename {ui => apps/main}/src/pages/login.tsx (90%) rename {ui => apps/main}/src/pages/oauth-signin.tsx (75%) rename {ui => apps/main}/src/pages/planning.tsx (97%) rename {ui => apps/main}/src/pages/reset-password.tsx (90%) rename {ui => apps/main}/src/pages/settings.tsx (93%) rename {ui => apps/main}/src/pages/signup.tsx (93%) rename {ui => apps/main}/src/pages/tablo.tsx (98%) rename {ui => apps/main}/src/providers/ChatProvider.tsx (100%) rename {ui => apps/main}/src/providers/DatadogRumProvider.tsx (91%) rename {ui => apps/main}/src/providers/UserStoreProvider.tsx (91%) rename {ui => apps/main}/src/setupTests.ts (100%) create mode 100644 apps/main/src/utils/iconHelpers.ts rename {ui => apps/main}/src/utils/testHelpers.tsx (90%) create mode 100644 apps/main/src/vite-env.d.ts create mode 100644 apps/main/stats.html create mode 100644 apps/main/tsconfig.app.json rename {ui => apps/main}/tsconfig.json (100%) rename {ui => apps/main}/tsconfig.node.json (100%) rename {ui => apps/main}/tsconfig.worker.json (100%) rename {ui => apps/main}/vite.config.d.ts (100%) create mode 100644 apps/main/vite.config.ts rename {ui => apps/main}/worker-configuration.d.ts (84%) create mode 100644 apps/main/worker/index.d.ts rename {ui => apps/main}/worker/index.ts (79%) rename {ui => apps/main}/wrangler.toml (100%) create mode 100644 package.json create mode 100644 packages/shared/package.json rename {ui => packages/shared}/src/contexts/SessionContext.tsx (75%) rename {ui => packages/shared}/src/contexts/ThemeContext.tsx (100%) create mode 100644 packages/shared/src/hooks/auth.ts rename {ui => packages/shared}/src/hooks/public.ts (51%) create mode 100644 packages/shared/src/hooks/tablos.ts rename {ui => packages/shared}/src/hooks/useClickOutside.ts (100%) create mode 100644 packages/shared/src/index.ts rename {ui => packages/shared}/src/lib/api.ts (69%) rename ui/src/lib/utils.ts => packages/shared/src/lib/cn.ts (100%) create mode 100644 packages/shared/src/lib/supabase.ts rename {ui => packages/shared}/src/lib/toast.ts (100%) rename {ui => packages/shared}/src/types/database.types.ts (100%) rename {ui => packages/shared}/src/types/events.types.ts (77%) rename {ui => packages/shared}/src/types/kanban.types.ts (100%) rename {ui => packages/shared}/src/types/removeNull.ts (100%) rename {ui => packages/shared}/src/types/tablos.types.ts (74%) rename {ui => packages/shared}/src/utils/helpers.ts (94%) create mode 100644 packages/shared/tsconfig.json create mode 100644 packages/shared/tsconfig.tsbuildinfo create mode 100644 packages/ui/components.json create mode 100644 packages/ui/package.json rename {ui/src/components/ui => packages/ui/src/components}/avatar.tsx (97%) rename {ui/src/components/ui => packages/ui/src/components}/badge.tsx (99%) rename {ui/src/components/ui => packages/ui/src/components}/button-group.tsx (95%) rename {ui/src/components/ui => packages/ui/src/components}/button.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/calendar.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/card.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/checkbox.tsx (96%) rename {ui/src/components/ui => packages/ui/src/components}/clipboard.tsx (96%) rename {ui/src/components/ui => packages/ui/src/components}/collapsible.tsx (100%) rename {ui/src/components/ui => packages/ui/src/components}/date-field.tsx (93%) rename {ui/src/components/ui => packages/ui/src/components}/date-picker.tsx (93%) rename {ui/src/components/ui => packages/ui/src/components}/dialog.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/dropdown-menu.tsx (99%) rename {ui/src/components/ui => packages/ui/src/components}/empty.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/field.tsx (97%) create mode 100644 packages/ui/src/components/index.ts rename {ui/src/components/ui => packages/ui/src/components}/input.tsx (95%) rename {ui/src/components/ui => packages/ui/src/components}/label.tsx (94%) rename {ui/src/components/ui => packages/ui/src/components}/popover.tsx (97%) rename {ui/src/components/ui => packages/ui/src/components}/select.tsx (99%) rename {ui/src/components/ui => packages/ui/src/components}/separator.tsx (94%) rename {ui/src/components/ui => packages/ui/src/components}/slider.tsx (96%) rename {ui/src/components/ui => packages/ui/src/components}/sonner.tsx (92%) rename {ui/src/components/ui => packages/ui/src/components}/switch.tsx (96%) rename {ui/src/components/ui => packages/ui/src/components}/tabs.tsx (98%) rename {ui/src/components/ui => packages/ui/src/components}/textarea.tsx (94%) rename {ui/src/components/ui => packages/ui/src/components}/time-input.tsx (91%) rename {ui/src/components/ui => packages/ui/src/components}/tooltip.tsx (96%) rename {ui/src/components/ui => packages/ui/src/components}/typography.tsx (98%) rename {ui/src/components/ui => packages/ui/src}/hooks/use-clipboard.ts (100%) create mode 100644 packages/ui/src/styles/globals.css create mode 100644 packages/ui/tsconfig.json create mode 100644 packages/ui/tsconfig.tsbuildinfo rename ui/pnpm-lock.yaml => pnpm-lock.yaml (90%) create mode 100644 pnpm-workspace.yaml create mode 100644 turbo.json delete mode 100644 ui/.gitignore delete mode 100644 ui/.wrangler/deploy/config.json delete mode 100644 ui/README.md delete mode 100644 ui/components.json delete mode 100644 ui/index.html delete mode 100644 ui/src/external/routes.tsx delete mode 100644 ui/src/hooks/support.ts delete mode 100644 ui/src/utils/iconHelpers.ts delete mode 100644 ui/stats.html delete mode 100644 ui/vite.config.ts delete mode 100644 ui/worker/index.d.ts diff --git a/.gitignore b/.gitignore index 882155b..2582c5c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,7 @@ __pycache__/ .pytest_cache/ .coverage htmlcov/ + +.turbo +dist +.wrangler \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..4afad3d --- /dev/null +++ b/README.md @@ -0,0 +1,172 @@ +# Xtablo Monorepo + +This is a Turborepo-based monorepo for the Xtablo project, containing multiple apps and shared packages. + +## Project Structure + +``` +xtablo-source/ +├── apps/ +│ ├── main/ # Main UI application +│ └── external/ # External booking widget microfrontend +├── packages/ +│ ├── ui-components/ # Shared UI components (buttons, inputs, etc.) +│ └── shared/ # Shared utilities, hooks, contexts, and types +├── api/ # TypeScript/Node.js API +├── backend/ # Python backend +├── go_backend/ # Go backend +└── xtablo-expo/ # React Native Expo app +``` + +## Getting Started + +### Prerequisites + +- Node.js 18+ and pnpm +- For other services: Python 3.11+, Go 1.21+ + +### Installation + +Install all dependencies: + +```bash +pnpm install +``` + +This will install dependencies for all apps and packages in the workspace. + +### Development + +Run all apps in development mode: + +```bash +turbo dev +``` + +Run specific app: + +```bash +# Main UI app (http://localhost:5173) +turbo dev --filter @xtablo/main + +# External microfrontend (http://localhost:5174) +turbo dev --filter @xtablo/external +``` + +### Building + +Build all apps: + +```bash +turbo build +``` + +Build specific app: + +```bash +turbo build --filter @xtablo/main +turbo build --filter @xtablo/external +``` + +### Linting and Formatting + +```bash +# Lint all packages +turbo lint + +# Format all packages +turbo format +``` + +## Packages + +### @xtablo/ui-components + +Shared UI components library used across the main and external apps. Contains all base UI components like buttons, inputs, dialogs, etc. + +**Usage:** + +```typescript +import { Button, Input, Dialog } from "@xtablo/ui-components"; +``` + +### @xtablo/shared + +Shared utilities, hooks, contexts, and types used across apps. + +**Usage:** + +```typescript +import { useSession } from "@xtablo/shared/contexts/SessionContext"; +import { api } from "@xtablo/shared/lib/api"; +import { Tables } from "@xtablo/shared/types/database.types"; +``` + +## Apps + +### Main (@xtablo/main) + +The main Xtablo application with full dashboard, planning, chat, and administrative features. + +**Local URL:** http://localhost:5173 + +### External (@xtablo/external) + +Embeddable booking widget that can be integrated into external websites. Supports both embedded and floating widget modes. + +**Local URL:** http://localhost:5174 + +**Usage:** + +- Embedded mode: `?mode=embed&eventTypeId=...` +- Floating widget: `?mode=widget&eventTypeId=...` + +## Turborepo Features + +This monorepo uses Turborepo for: + +- **Fast builds**: Parallel task execution and intelligent caching +- **Dependency management**: Automatic build ordering based on package dependencies +- **Code sharing**: Easy sharing of components and utilities between apps + +## Scripts + +- `turbo dev` - Start all apps in development mode +- `turbo build` - Build all apps +- `turbo lint` - Lint all packages +- `turbo format` - Format all packages +- `turbo typecheck` - Type check all packages +- `turbo test` - Run tests for all packages +- `turbo clean` - Clean all build artifacts and node_modules + +## Adding a New Package + +1. Create a new directory under `packages/` +2. Add a `package.json` with name `@xtablo/package-name` +3. Update `pnpm-workspace.yaml` if needed (already configured for `packages/*`) +4. Install in your app: `pnpm --filter @xtablo/your-app add @xtablo/package-name@workspace:*` + +## Migration Notes + +This project was migrated from a single UI app to a Turborepo monorepo with the following changes: + +- **Before**: Single `ui/` directory with all code +- **After**: + - `apps/main/` - Main application + - `apps/external/` - Separate microfrontend for booking widgets + - `packages/ui-components/` - Shared UI components + - `packages/shared/` - Shared utilities and logic + +All import paths have been updated to use workspace packages (`@xtablo/ui-components`, `@xtablo/shared`). + +## Contributing + +When adding new shared code: + +1. Add to the appropriate package (`ui-components` for UI, `shared` for logic/utils) +2. Export from the package's `index.ts` +3. Use the workspace import in your apps + +## License + +[Your License Here] diff --git a/apps/external/biome.json b/apps/external/biome.json new file mode 100644 index 0000000..3dc1855 --- /dev/null +++ b/apps/external/biome.json @@ -0,0 +1,342 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.5/schema.json", + "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, + "files": { + "includes": [ + "ui/src/**/*", + "ui/worker/**/*", + "ui/*.{ts,tsx,js,jsx,json}", + "api/src/**/*", + "api/*.{ts,tsx,js,jsx,json}", + "xtablo-expo/app/**/*", + "xtablo-expo/components/**/*", + "xtablo-expo/hooks/**/*", + "xtablo-expo/lib/**/*", + "xtablo-expo/providers/**/*", + "xtablo-expo/stores/**/*", + "xtablo-expo/types/**/*", + "xtablo-expo/*.{ts,tsx,js,jsx,json}" + ] + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "attributePosition": "auto" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": false, + "complexity": { + "noAdjacentSpacesInRegex": "error", + "noBannedTypes": "error", + "noExtraBooleanCast": "error", + "noUselessCatch": "error", + "noUselessEscapeInRegex": "error", + "noUselessTypeConstraint": "error" + }, + "correctness": { + "noChildrenProp": "error", + "noConstAssign": "error", + "noConstantCondition": "error", + "noEmptyCharacterClassInRegex": "error", + "noEmptyPattern": "error", + "noGlobalObjectCalls": "error", + "noInvalidBuiltinInstantiation": "error", + "noInvalidConstructorSuper": "error", + "noNonoctalDecimalEscape": "error", + "noPrecisionLoss": "error", + "noSelfAssign": "error", + "noSetterReturn": "error", + "noSwitchDeclarations": "error", + "noUndeclaredVariables": "error", + "noUnreachable": "error", + "noUnreachableSuper": "error", + "noUnsafeFinally": "error", + "noUnsafeOptionalChaining": "error", + "noUnusedLabels": "error", + "noUnusedPrivateClassMembers": "error", + "noUnusedVariables": "error", + "noUnusedImports": "error", + "useIsNan": "error", + "useJsxKeyInIterable": "error", + "useValidForDirection": "error", + "useValidTypeof": "error", + "useYield": "error" + }, + "nursery": {}, + "security": { "noDangerouslySetInnerHtmlWithChildren": "error" }, + "style": { + "noCommonJs": "error", + "noNamespace": "error", + "useArrayLiterals": "error", + "useAsConstAssertion": "error", + "useConst": "error", + "useTemplate": "error" + }, + "suspicious": { + "noAsyncPromiseExecutor": "error", + "noCatchAssign": "error", + "noClassAssign": "error", + "noCommentText": "error", + "noCompareNegZero": "error", + "noConstantBinaryExpressions": "error", + "noControlCharactersInRegex": "error", + "noDebugger": "error", + "noDuplicateCase": "error", + "noDuplicateClassMembers": "error", + "noDuplicateElseIf": "error", + "noDuplicateJsxProps": "error", + "noDuplicateObjectKeys": "error", + "noDuplicateParameters": "error", + "noEmptyBlockStatements": "error", + "noExplicitAny": "error", + "noExtraNonNullAssertion": "error", + "noFallthroughSwitchClause": "error", + "noFunctionAssign": "error", + "noGlobalAssign": "error", + "noImportAssign": "error", + "noIrregularWhitespace": "error", + "noMisleadingCharacterClass": "error", + "noMisleadingInstantiator": "error", + "noPrototypeBuiltins": "error", + "noRedeclare": "error", + "noShadowRestrictedNames": "error", + "noSparseArray": "error", + "noUnsafeDeclarationMerging": "error", + "noUnsafeNegation": "error", + "noUselessRegexBackrefs": "error", + "noWith": "error", + "useGetterReturn": "error", + "useNamespaceKeyword": "error" + } + } + }, + "javascript": { + "formatter": { + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingCommas": "es5", + "semicolons": "always", + "arrowParentheses": "always", + "bracketSameLine": false, + "quoteStyle": "double", + "attributePosition": "auto", + "bracketSpacing": true + }, + "globals": [ + "onanimationend", + "ongamepadconnected", + "onlostpointercapture", + "onanimationiteration", + "onkeyup", + "onmousedown", + "onanimationstart", + "onslotchange", + "onprogress", + "ontransitionstart", + "onpause", + "onended", + "onpointerover", + "onscrollend", + "onformdata", + "ontransitionrun", + "onanimationcancel", + "ondrag", + "onchange", + "onbeforeinstallprompt", + "onbeforexrselect", + "onmessage", + "ontransitioncancel", + "onpointerdown", + "onabort", + "onpointerout", + "oncuechange", + "ongotpointercapture", + "onscrollsnapchanging", + "onsearch", + "onsubmit", + "onstalled", + "onsuspend", + "onreset", + "onerror", + "onresize", + "onmouseenter", + "ongamepaddisconnected", + "ondragover", + "onbeforetoggle", + "onmouseover", + "onpagehide", + "onmousemove", + "onratechange", + "onmessageerror", + "onwheel", + "ondevicemotion", + "onauxclick", + "ontransitionend", + "onpaste", + "onpageswap", + "ononline", + "ondeviceorientationabsolute", + "onkeydown", + "onclose", + "onselect", + "onpageshow", + "onpointercancel", + "onbeforematch", + "onpointerrawupdate", + "ondragleave", + "onscrollsnapchange", + "onseeked", + "onwaiting", + "onbeforeunload", + "onplaying", + "onvolumechange", + "ondragend", + "onstorage", + "onloadeddata", + "onfocus", + "onoffline", + "onplay", + "onafterprint", + "onclick", + "oncut", + "onmouseout", + "ondblclick", + "oncanplay", + "onloadstart", + "onappinstalled", + "onpointermove", + "ontoggle", + "oncontextmenu", + "onblur", + "oncancel", + "onbeforeprint", + "oncontextrestored", + "onloadedmetadata", + "onpointerup", + "onlanguagechange", + "oncopy", + "onselectstart", + "onscroll", + "onload", + "ondragstart", + "onbeforeinput", + "oncanplaythrough", + "oninput", + "oninvalid", + "ontimeupdate", + "ondurationchange", + "onselectionchange", + "onmouseup", + "location", + "onkeypress", + "onpointerleave", + "oncontextlost", + "ondrop", + "onsecuritypolicyviolation", + "oncontentvisibilityautostatechange", + "ondeviceorientation", + "onseeking", + "onrejectionhandled", + "onunload", + "onmouseleave", + "onhashchange", + "onpointerenter", + "onmousewheel", + "onunhandledrejection", + "ondragenter", + "onpopstate", + "onpagereveal", + "onemptied" + ] + }, + "json": { + "parser": { "allowComments": true, "allowTrailingCommas": false }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineEnding": "lf", + "lineWidth": 100, + "trailingCommas": "none" + } + }, + "overrides": [ + { "linter": { "rules": { "suspicious": { "noExplicitAny": "off" } } } }, + { "linter": { "rules": { "style": { "useNodejsImportProtocol": "off" } } } }, + { + "linter": { + "rules": { + "style": { "useNodejsImportProtocol": "off" }, + "suspicious": { "noExplicitAny": "off" } + } + } + }, + { + "includes": [ + "ui/src/**/*.{ts,tsx}", + "ui/worker/**/*.{ts,tsx}", + "ui/*.{ts,tsx}", + "api/src/**/*.{ts,tsx}", + "api/*.{ts,tsx}", + "xtablo-expo/**/*.{ts,tsx}" + ], + "linter": { + "rules": { + "complexity": { "noArguments": "error" }, + "correctness": { + "noConstAssign": "off", + "noGlobalObjectCalls": "off", + "noInvalidBuiltinInstantiation": "off", + "noInvalidConstructorSuper": "off", + "noSetterReturn": "off", + "noUndeclaredVariables": "off", + "noUnreachable": "off", + "noUnreachableSuper": "off" + }, + "style": { "useConst": "error" }, + "suspicious": { + "noClassAssign": "off", + "noDuplicateClassMembers": "off", + "noDuplicateObjectKeys": "off", + "noDuplicateParameters": "off", + "noFunctionAssign": "off", + "noImportAssign": "off", + "noRedeclare": "off", + "noUnsafeNegation": "off", + "noVar": "error", + "useGetterReturn": "off" + } + } + } + }, + { + "includes": ["xtablo-expo/**/*.{js,jsx,ts,tsx}"], + "linter": { + "rules": { + "correctness": { + "noUndeclaredVariables": "off" + }, + "suspicious": { + "noExplicitAny": "warn" + } + } + } + }, + { + "includes": ["api/src/**/*.{js,ts}"], + "linter": { + "rules": { + "style": { + "noCommonJs": "off" + } + } + } + } + ] +} diff --git a/ui/external/index.html b/apps/external/index.html similarity index 70% rename from ui/external/index.html rename to apps/external/index.html index cffb5be..f49f514 100644 --- a/ui/external/index.html +++ b/apps/external/index.html @@ -3,9 +3,10 @@ + Xtablo External
- + diff --git a/apps/external/package.json b/apps/external/package.json new file mode 100644 index 0000000..3594da0 --- /dev/null +++ b/apps/external/package.json @@ -0,0 +1,41 @@ +{ + "name": "@xtablo/external", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "tsc -b && vite build", + "typecheck": "tsc --noEmit", + "lint": "biome check .", + "lint:fix": "biome check --write .", + "format": "biome format --write .", + "preview": "vite preview" + }, + "devDependencies": { + "@biomejs/biome": "2.2.5", + "@tailwindcss/vite": "^4.0.14", + "@types/react": "19.0.10", + "@types/react-dom": "19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "tailwindcss": "^4.0.14", + "tw-animate-css": "^1.4.0", + "typescript": "^5.7.0", + "vite": "^6.2.2", + "vite-tsconfig-paths": "^5.1.4" + }, + "dependencies": { + "@xtablo/ui": "workspace:*", + "@xtablo/shared": "workspace:*", + "@tanstack/react-query": "^5.69.0", + "clsx": "^2.1.1", + "lucide-react": "^0.460.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "react-router-dom": "^7.9.4", + "tailwind-merge": "^3.0.2", + "ts-pattern": "^5.6.2", + "zustand": "^5.0.5" + } +} + diff --git a/ui/public/icon.jpg b/apps/external/public/icon.jpg similarity index 100% rename from ui/public/icon.jpg rename to apps/external/public/icon.jpg diff --git a/ui/public/logo_dark.png b/apps/external/public/logo_dark.png similarity index 100% rename from ui/public/logo_dark.png rename to apps/external/public/logo_dark.png diff --git a/ui/public/logo_white.png b/apps/external/public/logo_white.png similarity index 100% rename from ui/public/logo_white.png rename to apps/external/public/logo_white.png diff --git a/ui/public/staging_icon.jpg b/apps/external/public/staging_icon.jpg similarity index 100% rename from ui/public/staging_icon.jpg rename to apps/external/public/staging_icon.jpg diff --git a/ui/public/vite.svg b/apps/external/public/vite.svg similarity index 100% rename from ui/public/vite.svg rename to apps/external/public/vite.svg diff --git a/ui/src/components/CustomModal.tsx b/apps/external/src/CustomModal.tsx similarity index 94% rename from ui/src/components/CustomModal.tsx rename to apps/external/src/CustomModal.tsx index c52c0ea..2aaa242 100644 --- a/ui/src/components/CustomModal.tsx +++ b/apps/external/src/CustomModal.tsx @@ -1,5 +1,5 @@ -import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@ui/components/ui/dialog"; -import { cn } from "@ui/lib/utils"; +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@xtablo/ui/components/dialog"; +import { cn } from "@xtablo/shared"; // Custom Modal Component - now using shadcn/ui Dialog interface CustomModalProps { diff --git a/ui/src/external/EmbeddedBookingPage.tsx b/apps/external/src/EmbeddedBookingPage.tsx similarity index 95% rename from ui/src/external/EmbeddedBookingPage.tsx rename to apps/external/src/EmbeddedBookingPage.tsx index e0b0b4f..be4e9c3 100644 --- a/ui/src/external/EmbeddedBookingPage.tsx +++ b/apps/external/src/EmbeddedBookingPage.tsx @@ -1,16 +1,16 @@ -import { CustomModal } from "@ui/components/CustomModal"; -import { LoadingSpinner } from "@ui/components/LoadingSpinner"; -import { Button } from "@ui/components/ui/button"; -import { FieldError } from "@ui/components/ui/field"; -import { Input } from "@ui/components/ui/input"; -import { Label } from "@ui/components/ui/label"; -import { Text, TypographyH3, TypographyH4, TypographyMuted } from "@ui/components/ui/typography"; -import { useSession } from "@ui/contexts/SessionContext"; -import { useSignUpWithoutPassword } from "@ui/hooks/auth"; -import { TimeSlot, usePublicSlots } from "@ui/hooks/public"; -import { useCreateTabloWithOwner } from "@ui/hooks/tablos"; -import { useMaybeUser } from "@ui/providers/UserStoreProvider"; -import { EventInsertInTablo } from "@ui/types/events.types"; +import { CustomModal } from "./CustomModal"; +import { LoadingSpinner } from "./LoadingSpinner"; +import { Button } from "@xtablo/ui/components/button"; +import { FieldError } from "@xtablo/ui/components/field"; +import { Input } from "@xtablo/ui/components/input"; +import { Label } from "@xtablo/ui/components/label"; +import { Text, TypographyH3, TypographyH4, TypographyMuted } from "@xtablo/ui/components/typography"; +import { useSession } from "@xtablo/shared/contexts/SessionContext"; +import { useSignUpWithoutPassword } from "@xtablo/shared/hooks/auth"; +import { TimeSlot, usePublicSlots } from "@xtablo/shared/hooks/public"; +import { useCreateTabloWithOwner } from "@xtablo/shared"; +import { useMaybeUser } from "./UserStoreProvider"; +import { EventInsertInTablo } from "@xtablo/shared/types/events.types"; import { CalendarIcon, ChevronLeftIcon, @@ -22,6 +22,8 @@ import { import { useState } from "react"; import { useParams, useSearchParams } from "react-router-dom"; import { twMerge } from "tailwind-merge"; +import { supabase } from "./lib/supabase"; +import { api } from "./lib/api"; type ColorVariant = "black" | "white" | "blue" | "purple" | "green" | "orange" | "red"; @@ -187,16 +189,14 @@ const getMutedTextColorFromBackground = (variant: ColorVariant): string => { }; export function EmbeddedBookingPage() { - const { user_info, event_type_standard_name } = useParams<{ - user_info: string; - event_type_standard_name: string; - }>(); + const params = useParams(); const [searchParams] = useSearchParams(); - const { mutateAsync: signUpWithoutPassword } = useSignUpWithoutPassword(); + const { mutateAsync: signUpWithoutPassword } = useSignUpWithoutPassword(supabase, api); const { session } = useSession(); const user = useMaybeUser(); - const shortUserId = user_info?.substring(user_info.lastIndexOf("-") + 1); + const userInfo = params.userInfo as string; + const eventTypeStandardName = params.eventTypeStandardName as string; // Get variants from URL params or props, with fallback to purple const backgroundVariant = (searchParams.get("backgroundVariant") as ColorVariant) || "black"; const buttonVariant = (searchParams.get("buttonVariant") as ColorVariant) || "purple"; @@ -207,12 +207,21 @@ export function EmbeddedBookingPage() { const txtColor = getTextColorFromBackground(backgroundVariant); const mutedTxtColor = getMutedTextColorFromBackground(backgroundVariant); - const { data: publicSlots, isLoading: isLoadingSlots } = usePublicSlots( - shortUserId || "", - event_type_standard_name || "" - ); + const shortUserId = userInfo?.substring(userInfo.lastIndexOf("-") + 1); - const { mutateAsync: createTabloWithOwner } = useCreateTabloWithOwner(); + console.log({shortUserId, eventTypeStandardName}) + const { data: publicSlots, isLoading: isLoadingSlots } = usePublicSlots( + api, + shortUserId || "", + eventTypeStandardName || "" + ); + + + const { mutateAsync: createTabloWithOwner } = useCreateTabloWithOwner(api, + () => { + handleCloseModal(); + } + ); const userProfile = publicSlots?.user; const eventType = publicSlots?.eventType; @@ -460,7 +469,7 @@ export function EmbeddedBookingPage() { {/* Left Side - Event Details */}
@@ -512,7 +521,7 @@ export function EmbeddedBookingPage() {
(); + const params = useParams(); const [searchParams] = useSearchParams(); - const { mutateAsync: signUpWithoutPassword } = useSignUpWithoutPassword(); + const { mutateAsync: signUpWithoutPassword } = useSignUpWithoutPassword(supabase, api); const { session } = useSession(); const user = useMaybeUser(); - const shortUserId = user_info?.substring(user_info.lastIndexOf("-") + 1); + const userInfo = params.userInfo as string; + const eventTypeStandardName = params.eventTypeStandardName as string; + const shortUserId = userInfo?.substring(userInfo.lastIndexOf("-") + 1); // Get variants from URL params with fallback to purple const buttonVariant = (searchParams.get("buttonVariant") as ColorVariant) || "purple"; @@ -125,11 +127,17 @@ export function FloatingBookingWidget() { const btnColors = buttonColors[buttonVariant]; const { data: publicSlots, isLoading: isLoadingSlots } = usePublicSlots( + api, shortUserId || "", - event_type_standard_name || "" + eventTypeStandardName || "" ); - const { mutateAsync: createTabloWithOwner } = useCreateTabloWithOwner(); + const { mutateAsync: createTabloWithOwner } = useCreateTabloWithOwner(api, + () => { + handleCloseModal(); + setIsWidgetOpen(false); + } + ); const userProfile = publicSlots?.user; const eventType = publicSlots?.eventType; @@ -411,10 +419,10 @@ export function FloatingBookingWidget() { {userProfile?.name ) : ( -
+
)} @@ -430,7 +438,7 @@ export function FloatingBookingWidget() {
} /> @@ -57,7 +70,7 @@ describe("PublicRoute", () => { it("renders public content when user is not authenticated", async () => { renderWithRouter( - + }> Login Page
} /> diff --git a/ui/src/components/AvailabilityCard.tsx b/apps/main/src/components/AvailabilityCard.tsx similarity index 97% rename from ui/src/components/AvailabilityCard.tsx rename to apps/main/src/components/AvailabilityCard.tsx index 675788c..199d9c9 100644 --- a/ui/src/components/AvailabilityCard.tsx +++ b/apps/main/src/components/AvailabilityCard.tsx @@ -1,7 +1,7 @@ -import { Button } from "@ui/components/ui/button"; -import { Card, CardAction, CardContent, CardHeader, CardTitle } from "@ui/components/ui/card"; -import { Switch } from "@ui/components/ui/switch"; -import { TimeInput } from "@ui/components/ui/time-input"; +import { Button } from "@xtablo/ui/components/button"; +import { Card, CardAction, CardContent, CardHeader, CardTitle } from "@xtablo/ui/components/card"; +import { Switch } from "@xtablo/ui/components/switch"; +import { TimeInput } from "@xtablo/ui/components/time-input"; import { Copy as CopyIcon, Minus as MinusIcon, Plus as PlusIcon } from "lucide-react"; interface TimeRange { diff --git a/ui/src/components/AvailabilityVisualization.tsx b/apps/main/src/components/AvailabilityVisualization.tsx similarity index 80% rename from ui/src/components/AvailabilityVisualization.tsx rename to apps/main/src/components/AvailabilityVisualization.tsx index d9532d6..96f74bd 100644 --- a/ui/src/components/AvailabilityVisualization.tsx +++ b/apps/main/src/components/AvailabilityVisualization.tsx @@ -1,5 +1,5 @@ -import { Text } from "@ui/components/ui/typography"; -import { WeeklyAvailability } from "@ui/hooks/availabilities"; +import { Text } from "@xtablo/ui/components/typography"; +import { WeeklyAvailability } from "../hooks/availabilities"; // Check if a time slot is available for a given day const isTimeSlotAvailable = ( @@ -65,13 +65,13 @@ export const AvailabilityVisualization = ({
{/* Weekly Calendar Header */}
-
+
Heure
{DAYS_OF_WEEK.map((day) => (
{DAYS_OF_WEEK_DISPLAY[day]} @@ -93,7 +93,7 @@ export const AvailabilityVisualization = ({ key={timeSlot} className="grid grid-cols-8 border-b border-gray-100 dark:border-gray-700 hover:bg-slate-50/50 dark:hover:bg-slate-800/50 transition-colors duration-150" > -
+
{timeSlot} @@ -101,10 +101,10 @@ export const AvailabilityVisualization = ({ {DAYS_OF_WEEK.map((day) => (
{isTimeSlotAvailable(day, timeSlot, draftAvailabilities) ? ( -
+
) : ( diff --git a/ui/src/components/BrandButtons/LoginWithGoogle.test.tsx b/apps/main/src/components/BrandButtons/LoginWithGoogle.test.tsx similarity index 95% rename from ui/src/components/BrandButtons/LoginWithGoogle.test.tsx rename to apps/main/src/components/BrandButtons/LoginWithGoogle.test.tsx index 728a0cc..3f155e5 100644 --- a/ui/src/components/BrandButtons/LoginWithGoogle.test.tsx +++ b/apps/main/src/components/BrandButtons/LoginWithGoogle.test.tsx @@ -1,6 +1,6 @@ import { fireEvent, render, screen } from "@testing-library/react"; import { LoginWithGoogle } from "@ui/components/BrandButtons/LoginWithGoogle"; -import { useLoginGoogle } from "@ui/hooks/auth"; +import { useLoginGoogle } from "../../hooks/auth"; import { vi } from "vitest"; vi.mock("../../hooks/auth", () => ({ diff --git a/ui/src/components/BrandButtons/LoginWithGoogle.tsx b/apps/main/src/components/BrandButtons/LoginWithGoogle.tsx similarity index 100% rename from ui/src/components/BrandButtons/LoginWithGoogle.tsx rename to apps/main/src/components/BrandButtons/LoginWithGoogle.tsx diff --git a/ui/src/components/BrandButtons/login-with-google.css b/apps/main/src/components/BrandButtons/login-with-google.css similarity index 100% rename from ui/src/components/BrandButtons/login-with-google.css rename to apps/main/src/components/BrandButtons/login-with-google.css diff --git a/ui/src/components/ChannelBadge.tsx b/apps/main/src/components/ChannelBadge.tsx similarity index 92% rename from ui/src/components/ChannelBadge.tsx rename to apps/main/src/components/ChannelBadge.tsx index ea78b54..9dbdc51 100644 --- a/ui/src/components/ChannelBadge.tsx +++ b/apps/main/src/components/ChannelBadge.tsx @@ -1,4 +1,4 @@ -import { UserTablo } from "@ui/types/tablos.types"; +import { UserTablo } from "@xtablo/shared/types/tablos.types"; import { twMerge } from "tailwind-merge"; export const ChannelBadge = ({ diff --git a/ui/src/components/ChannelPreview.tsx b/apps/main/src/components/ChannelPreview.tsx similarity index 95% rename from ui/src/components/ChannelPreview.tsx rename to apps/main/src/components/ChannelPreview.tsx index 2cca8ae..e3a9294 100644 --- a/ui/src/components/ChannelPreview.tsx +++ b/apps/main/src/components/ChannelPreview.tsx @@ -1,6 +1,6 @@ import { ChannelBadge } from "@ui/components/ChannelBadge"; -import { Badge } from "@ui/components/ui/badge"; -import { UserTablo } from "@ui/types/tablos.types"; +import { Badge } from "@xtablo/ui/components/badge"; +import { UserTablo } from "@xtablo/shared/types/tablos.types"; import { ReactNode } from "react"; import { Channel } from "stream-chat"; import { twMerge } from "tailwind-merge"; @@ -104,7 +104,7 @@ export function ChannelPreview({ {displayTitle} {timestamp && ( - + {formatTimestamp(timestamp)} )} @@ -117,7 +117,7 @@ export function ChannelPreview({ {/* Unread count badge */} {unreadCount > 0 && ( -
+
void; + title: string; + children: React.ReactNode; + width?: "sm" | "md" | "lg" | "xl" | "2xl" | "full" | "auto"; +} + +export function CustomModal({ isOpen, onClose, title, children, width = "md" }: CustomModalProps) { + const getWidthClasses = () => { + switch (width) { + case "sm": + return "max-w-sm"; + case "md": + return "max-w-md"; + case "lg": + return "max-w-lg"; + case "xl": + return "max-w-xl"; + case "2xl": + return "max-w-2xl"; + case "full": + return "max-w-full mx-4"; + case "auto": + return "w-auto min-w-80 max-w-[90vw]"; + default: + return "max-w-md"; + } + }; + + return ( + + + + {title} + +
{children}
+
+
+ ); +} diff --git a/ui/src/components/DeleteTabloModal.tsx b/apps/main/src/components/DeleteTabloModal.tsx similarity index 98% rename from ui/src/components/DeleteTabloModal.tsx rename to apps/main/src/components/DeleteTabloModal.tsx index af8d4c5..5af4253 100644 --- a/ui/src/components/DeleteTabloModal.tsx +++ b/apps/main/src/components/DeleteTabloModal.tsx @@ -1,4 +1,4 @@ -import { UserTablo } from "@ui/types/tablos.types"; +import { UserTablo } from "@xtablo/shared/types/tablos.types"; import { ClickOutside } from "./ClickOutside"; interface DeleteTabloModalProps { diff --git a/ui/src/components/EmbedConfigModal.tsx b/apps/main/src/components/EmbedConfigModal.tsx similarity index 89% rename from ui/src/components/EmbedConfigModal.tsx rename to apps/main/src/components/EmbedConfigModal.tsx index 90b53ae..257e6c8 100644 --- a/ui/src/components/EmbedConfigModal.tsx +++ b/apps/main/src/components/EmbedConfigModal.tsx @@ -1,26 +1,26 @@ -import { Button } from "@ui/components/ui/button"; +import { Button } from "@xtablo/ui/components/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, -} from "@ui/components/ui/dialog"; -import { Label } from "@ui/components/ui/label"; +} from "@xtablo/ui/components/dialog"; +import { Label } from "@xtablo/ui/components/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from "@ui/components/ui/select"; -import { CopyButton } from "@ui/components/ui/clipboard"; +} from "@xtablo/ui/components/select"; +import { CopyButton } from "@xtablo/ui/components/clipboard"; import { useState } from "react"; -import { TypographyMuted, TypographyP } from "@ui/components/ui/typography"; +import { TypographyMuted, TypographyP } from "@xtablo/ui/components/typography"; type ColorVariant = "black" | "white" | "blue" | "purple" | "green" | "orange" | "red"; -type EmbedType = "full" | "floating"; +export type EmbedType = "embed" | "floating" | "normal"; interface EmbedConfig { embedType: EmbedType; @@ -31,30 +31,25 @@ interface EmbedConfig { interface EmbedConfigModalProps { isOpen: boolean; onClose: () => void; - baseEmbedUrl: string; - baseFloatingUrl: string; + buildPublicLink: (type: "embed" | "floating" | "normal") => string; } -export function EmbedConfigModal({ - isOpen, - onClose, - baseEmbedUrl, - baseFloatingUrl, -}: EmbedConfigModalProps) { +export function EmbedConfigModal({ isOpen, onClose, buildPublicLink }: EmbedConfigModalProps) { const [embedConfig, setEmbedConfig] = useState({ - embedType: "full", + embedType: "embed", backgroundVariant: "purple", buttonVariant: "purple", }); const getEmbedUrl = () => { - const baseUrl = embedConfig.embedType === "full" ? baseEmbedUrl : baseFloatingUrl; + const baseUrl = buildPublicLink(embedConfig.embedType); const params = new URLSearchParams({ + mode: "embed", buttonVariant: embedConfig.buttonVariant, }); // Only add backgroundVariant for full embed - if (embedConfig.embedType === "full") { + if (embedConfig.embedType === "embed") { params.set("backgroundVariant", embedConfig.backgroundVariant); } @@ -122,7 +117,7 @@ export function EmbedConfigModal({ - +
Page complète
@@ -136,7 +131,7 @@ export function EmbedConfigModal({
- {embedConfig.embedType === "full" && ( + {embedConfig.embedType === "embed" && (