@wakastellar/ui 2.0.0 → 2.1.0
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/dist/cli/commands/add.d.ts +7 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/list.d.ts +5 -0
- package/dist/cli/commands/search.d.ts +1 -0
- package/dist/cli/index.cjs +4844 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/utils/config.d.ts +29 -0
- package/dist/cli/utils/logger.d.ts +20 -0
- package/dist/cli/utils/registry.d.ts +23 -0
- package/package.json +14 -3
- package/src/blocks/activity-timeline/index.tsx +586 -0
- package/src/blocks/calendar-view/index.tsx +756 -0
- package/src/blocks/chat/index.tsx +1018 -0
- package/src/blocks/chat/widget.tsx +504 -0
- package/src/blocks/dashboard/index.tsx +522 -0
- package/src/blocks/empty-states/index.tsx +452 -0
- package/src/blocks/error-pages/index.tsx +426 -0
- package/src/blocks/faq/index.tsx +479 -0
- package/src/blocks/file-manager/index.tsx +890 -0
- package/src/blocks/footer/index.tsx +133 -0
- package/src/blocks/header/index.tsx +357 -0
- package/src/blocks/headtab/index.tsx +139 -0
- package/src/blocks/i18n-editor/index.tsx +1016 -0
- package/src/blocks/index.ts +80 -0
- package/src/blocks/kanban-board/index.tsx +779 -0
- package/src/blocks/landing/index.tsx +677 -0
- package/src/blocks/language-selector/index.tsx +88 -0
- package/src/blocks/layout/index.tsx +159 -0
- package/src/blocks/login/index.tsx +339 -0
- package/src/blocks/login/types.ts +131 -0
- package/src/blocks/pricing/index.tsx +564 -0
- package/src/blocks/profile/index.tsx +746 -0
- package/src/blocks/settings/index.tsx +558 -0
- package/src/blocks/sidebar/index.tsx +713 -0
- package/src/blocks/theme-creator-block/index.tsx +835 -0
- package/src/blocks/user-management/index.tsx +1037 -0
- package/src/blocks/wizard/index.tsx +719 -0
- package/src/components/DataTable/DataTable.tsx +406 -0
- package/src/components/DataTable/DataTableAdvanced.tsx +720 -0
- package/src/components/DataTable/DataTableBody.tsx +216 -0
- package/src/components/DataTable/DataTableCell.tsx +172 -0
- package/src/components/DataTable/DataTableColumnResizer.tsx +62 -0
- package/src/components/DataTable/DataTableConflictResolver.tsx +478 -0
- package/src/components/DataTable/DataTableContextMenu.tsx +219 -0
- package/src/components/DataTable/DataTableEditCell.tsx +279 -0
- package/src/components/DataTable/DataTableFilterBuilder.tsx +519 -0
- package/src/components/DataTable/DataTableFilters.tsx +535 -0
- package/src/components/DataTable/DataTableGrouping.tsx +147 -0
- package/src/components/DataTable/DataTableHeader.tsx +172 -0
- package/src/components/DataTable/DataTablePagination.tsx +125 -0
- package/src/components/DataTable/DataTableSelection.tsx +269 -0
- package/src/components/DataTable/DataTableSyncStatus.tsx +281 -0
- package/src/components/DataTable/DataTableToolbar.tsx +262 -0
- package/src/components/DataTable/README.md +446 -0
- package/src/components/DataTable/__tests__/DataTableAdvanced.test.tsx +426 -0
- package/src/components/DataTable/__tests__/DataTableEdit.test.tsx +329 -0
- package/src/components/DataTable/__tests__/useDataTableAdvanced.test.ts +455 -0
- package/src/components/DataTable/examples/EditExample.tsx +166 -0
- package/src/components/DataTable/formatters/index.ts +335 -0
- package/src/components/DataTable/hooks/__tests__/useDataTableEdit.test.ts +239 -0
- package/src/components/DataTable/hooks/useDataTable.ts +145 -0
- package/src/components/DataTable/hooks/useDataTableAdvanced.ts +342 -0
- package/src/components/DataTable/hooks/useDataTableAdvancedFilters.ts +637 -0
- package/src/components/DataTable/hooks/useDataTableColumnTemplates.ts +186 -0
- package/src/components/DataTable/hooks/useDataTableEdit.ts +167 -0
- package/src/components/DataTable/hooks/useDataTableExport.ts +227 -0
- package/src/components/DataTable/hooks/useDataTableImport.ts +216 -0
- package/src/components/DataTable/hooks/useDataTableOffline.ts +481 -0
- package/src/components/DataTable/hooks/useDataTableTheme.ts +213 -0
- package/src/components/DataTable/hooks/useDataTableVirtualization.ts +99 -0
- package/src/components/DataTable/hooks/useTableLayout.ts +85 -0
- package/src/components/DataTable/index.ts +81 -0
- package/src/components/DataTable/services/IndexedDBService.ts +504 -0
- package/src/components/DataTable/templates/index.tsx +803 -0
- package/src/components/DataTable/types.ts +504 -0
- package/src/components/DataTable/utils.ts +164 -0
- package/src/components/DataTable/workers/exportWorker.ts +213 -0
- package/src/components/accordion/index.tsx +61 -0
- package/src/components/alert/index.tsx +61 -0
- package/src/components/alert-dialog/index.tsx +146 -0
- package/src/components/aspect-ratio/index.tsx +12 -0
- package/src/components/avatar/index.tsx +54 -0
- package/src/components/badge/Badge.stories.tsx +64 -0
- package/src/components/badge/index.tsx +38 -0
- package/src/components/button/Button.stories.tsx +173 -0
- package/src/components/button/index.tsx +56 -0
- package/src/components/calendar/index.tsx +73 -0
- package/src/components/card/index.tsx +78 -0
- package/src/components/checkbox/index.tsx +34 -0
- package/src/components/code/index.tsx +229 -0
- package/src/components/collapsible/index.tsx +16 -0
- package/src/components/command/index.tsx +162 -0
- package/src/components/context-menu/index.tsx +204 -0
- package/src/components/dialog/index.tsx +126 -0
- package/src/components/dropdown-menu/index.tsx +204 -0
- package/src/components/error-boundary/ErrorBoundary.tsx +281 -0
- package/src/components/error-boundary/index.ts +7 -0
- package/src/components/form/index.tsx +183 -0
- package/src/components/hover-card/index.tsx +33 -0
- package/src/components/index.ts +368 -0
- package/src/components/input/Input.stories.tsx +100 -0
- package/src/components/input/index.tsx +27 -0
- package/src/components/input-otp/index.tsx +277 -0
- package/src/components/label/index.tsx +30 -0
- package/src/components/language-selector/index.tsx +341 -0
- package/src/components/menubar/index.tsx +240 -0
- package/src/components/navigation-menu/index.tsx +134 -0
- package/src/components/popover/index.tsx +35 -0
- package/src/components/progress/index.tsx +32 -0
- package/src/components/radio-group/index.tsx +48 -0
- package/src/components/scroll-area/index.tsx +52 -0
- package/src/components/select/index.tsx +164 -0
- package/src/components/separator/index.tsx +35 -0
- package/src/components/sheet/index.tsx +147 -0
- package/src/components/skeleton/index.tsx +22 -0
- package/src/components/slider/index.tsx +32 -0
- package/src/components/switch/index.tsx +33 -0
- package/src/components/table/index.tsx +117 -0
- package/src/components/tabs/index.tsx +59 -0
- package/src/components/textarea/index.tsx +30 -0
- package/src/components/theme-selector/index.tsx +327 -0
- package/src/components/toast/index.tsx +133 -0
- package/src/components/toaster/index.tsx +34 -0
- package/src/components/toggle/index.tsx +49 -0
- package/src/components/tooltip/index.tsx +34 -0
- package/src/components/typography/index.tsx +276 -0
- package/src/components/waka-3d-pie-chart/index.tsx +486 -0
- package/src/components/waka-achievement-unlock/index.tsx +716 -0
- package/src/components/waka-activity-feed/index.tsx +686 -0
- package/src/components/waka-address-autocomplete/index.tsx +1202 -0
- package/src/components/waka-admincrumb/index.tsx +349 -0
- package/src/components/waka-alert-stack/index.tsx +827 -0
- package/src/components/waka-allocation-matrix/index.tsx +1278 -0
- package/src/components/waka-approval-chain/index.tsx +766 -0
- package/src/components/waka-audit-log/index.tsx +1475 -0
- package/src/components/waka-autocomplete/index.tsx +358 -0
- package/src/components/waka-badge-showcase/index.tsx +704 -0
- package/src/components/waka-barcode/index.tsx +260 -0
- package/src/components/waka-biometric-prompt/index.tsx +765 -0
- package/src/components/waka-bottom-sheet/index.tsx +495 -0
- package/src/components/waka-breadcrumb/index.tsx +376 -0
- package/src/components/waka-breadcrumb-path/index.tsx +513 -0
- package/src/components/waka-budget-burn/index.tsx +1234 -0
- package/src/components/waka-capacity-planner/index.tsx +1107 -0
- package/src/components/waka-carousel/index.tsx +893 -0
- package/src/components/waka-cart-summary/index.tsx +1055 -0
- package/src/components/waka-challenge-timer/index.tsx +1044 -0
- package/src/components/waka-charts/WakaAreaChart.tsx +251 -0
- package/src/components/waka-charts/WakaBarChart.tsx +222 -0
- package/src/components/waka-charts/WakaChart.tsx +124 -0
- package/src/components/waka-charts/WakaLineChart.tsx +219 -0
- package/src/components/waka-charts/WakaMiniChart.tsx +133 -0
- package/src/components/waka-charts/WakaPieChart.tsx +214 -0
- package/src/components/waka-charts/WakaSparkline.tsx +229 -0
- package/src/components/waka-charts/dataTableHelpers.ts +109 -0
- package/src/components/waka-charts/hooks/useChartTheme.ts +123 -0
- package/src/components/waka-charts/hooks/useRechartsLoader.ts +234 -0
- package/src/components/waka-charts/index.ts +90 -0
- package/src/components/waka-charts/types.ts +330 -0
- package/src/components/waka-chat-bubble/index.tsx +1060 -0
- package/src/components/waka-checklist/index.tsx +1067 -0
- package/src/components/waka-checkout-stepper/index.tsx +976 -0
- package/src/components/waka-cohort-table/index.tsx +1011 -0
- package/src/components/waka-color-picker/index.tsx +447 -0
- package/src/components/waka-combo-counter/index.tsx +864 -0
- package/src/components/waka-combobox/index.tsx +497 -0
- package/src/components/waka-command-bar/index.tsx +403 -0
- package/src/components/waka-compare-period/index.tsx +1230 -0
- package/src/components/waka-connection-matrix/index.tsx +1053 -0
- package/src/components/waka-contribution-graph/index.tsx +552 -0
- package/src/components/waka-cost-breakdown/index.tsx +1065 -0
- package/src/components/waka-coupon-input/index.tsx +592 -0
- package/src/components/waka-credit-card-input/index.tsx +982 -0
- package/src/components/waka-daily-reward/index.tsx +762 -0
- package/src/components/waka-date-range-picker/index.tsx +378 -0
- package/src/components/waka-datetime-picker/index.tsx +793 -0
- package/src/components/waka-datetime-picker.form-integration/index.tsx +402 -0
- package/src/components/waka-deployment-lane/index.tsx +673 -0
- package/src/components/waka-device-trust/index.tsx +1259 -0
- package/src/components/waka-dock/index.tsx +285 -0
- package/src/components/waka-drawer/index.tsx +319 -0
- package/src/components/waka-empty-state/index.tsx +545 -0
- package/src/components/waka-error-shake/index.tsx +398 -0
- package/src/components/waka-feature-announcement/index.tsx +991 -0
- package/src/components/waka-file-upload/index.tsx +437 -0
- package/src/components/waka-floating-nav/index.tsx +413 -0
- package/src/components/waka-flow-diagram/index.tsx +508 -0
- package/src/components/waka-funnel-chart/index.tsx +823 -0
- package/src/components/waka-glow-card/index.tsx +246 -0
- package/src/components/waka-goal-progress/index.tsx +1025 -0
- package/src/components/waka-haptic-button/index.tsx +388 -0
- package/src/components/waka-health-pulse/index.tsx +451 -0
- package/src/components/waka-heatmap/index.tsx +1026 -0
- package/src/components/waka-hotspot/index.tsx +682 -0
- package/src/components/waka-image/index.tsx +373 -0
- package/src/components/waka-incident-timeline/index.tsx +686 -0
- package/src/components/waka-invoice-preview/index.tsx +829 -0
- package/src/components/waka-kanban/index.tsx +646 -0
- package/src/components/waka-kpi-dashboard/index.tsx +755 -0
- package/src/components/waka-leaderboard/index.tsx +746 -0
- package/src/components/waka-level-progress/index.tsx +665 -0
- package/src/components/waka-liquid-button/index.tsx +520 -0
- package/src/components/waka-loading-orbit/index.tsx +478 -0
- package/src/components/waka-loot-box/index.tsx +1091 -0
- package/src/components/waka-magic-link/index.tsx +321 -0
- package/src/components/waka-magnetic-button/index.tsx +567 -0
- package/src/components/waka-mention-input/index.tsx +953 -0
- package/src/components/waka-metric-sparkline/index.tsx +627 -0
- package/src/components/waka-milestone-road/index.tsx +1064 -0
- package/src/components/waka-modal/index.tsx +374 -0
- package/src/components/waka-morph-button/index.tsx +495 -0
- package/src/components/waka-network-topology/index.tsx +801 -0
- package/src/components/waka-notifications/index.tsx +414 -0
- package/src/components/waka-number-input/index.tsx +373 -0
- package/src/components/waka-orbital-menu/index.tsx +445 -0
- package/src/components/waka-order-tracker/index.tsx +1041 -0
- package/src/components/waka-pagination/index.tsx +393 -0
- package/src/components/waka-password-strength/index.tsx +824 -0
- package/src/components/waka-payment-method-picker/index.tsx +715 -0
- package/src/components/waka-permission-matrix/index.tsx +1302 -0
- package/src/components/waka-phone-input/index.tsx +801 -0
- package/src/components/waka-pipeline-view/index.tsx +604 -0
- package/src/components/waka-player-card/index.tsx +691 -0
- package/src/components/waka-points-popup/index.tsx +366 -0
- package/src/components/waka-power-up/index.tsx +1155 -0
- package/src/components/waka-presence-indicator/index.tsx +1181 -0
- package/src/components/waka-pricing-table/index.tsx +755 -0
- package/src/components/waka-product-card/index.tsx +786 -0
- package/src/components/waka-progress-onboarding/index.tsx +878 -0
- package/src/components/waka-pull-to-refresh/index.tsx +451 -0
- package/src/components/waka-qrcode/index.tsx +232 -0
- package/src/components/waka-quest-card/index.tsx +1275 -0
- package/src/components/waka-quota-bar/index.tsx +693 -0
- package/src/components/waka-radar-score/index.tsx +512 -0
- package/src/components/waka-rank-badge/index.tsx +813 -0
- package/src/components/waka-rating-input/index.tsx +560 -0
- package/src/components/waka-reaction-picker/index.tsx +1062 -0
- package/src/components/waka-region-map/index.tsx +730 -0
- package/src/components/waka-resource-gauge/index.tsx +654 -0
- package/src/components/waka-resource-pool/index.tsx +1035 -0
- package/src/components/waka-rich-text-editor/index.tsx +594 -0
- package/src/components/waka-rollback-slider/index.tsx +891 -0
- package/src/components/waka-sankey-diagram/index.tsx +1032 -0
- package/src/components/waka-schedule-picker/index.tsx +1060 -0
- package/src/components/waka-scratch-card/index.tsx +914 -0
- package/src/components/waka-season-pass/index.tsx +886 -0
- package/src/components/waka-security-score/index.tsx +1126 -0
- package/src/components/waka-segmented-control/index.tsx +238 -0
- package/src/components/waka-server-rack/index.tsx +764 -0
- package/src/components/waka-session-manager/index.tsx +815 -0
- package/src/components/waka-signature-pad/index.tsx +744 -0
- package/src/components/waka-skeleton-wave/index.tsx +454 -0
- package/src/components/waka-skill-tree/index.tsx +1031 -0
- package/src/components/waka-sla-tracker/index.tsx +798 -0
- package/src/components/waka-slider-range/index.tsx +765 -0
- package/src/components/waka-spin-wheel/index.tsx +671 -0
- package/src/components/waka-spinner/index.tsx +284 -0
- package/src/components/waka-spotlight/index.tsx +410 -0
- package/src/components/waka-stat/index.tsx +428 -0
- package/src/components/waka-stats-hexagon/index.tsx +824 -0
- package/src/components/waka-status-matrix/index.tsx +565 -0
- package/src/components/waka-stepper/index.tsx +489 -0
- package/src/components/waka-streak-counter/index.tsx +334 -0
- package/src/components/waka-success-explosion/index.tsx +453 -0
- package/src/components/waka-swipe-card/index.tsx +574 -0
- package/src/components/waka-tabs-morph/index.tsx +509 -0
- package/src/components/waka-tag-input/index.tsx +877 -0
- package/src/components/waka-team-banner/index.tsx +1183 -0
- package/src/components/waka-terminal-output/index.tsx +836 -0
- package/src/components/waka-theme-creator/index.tsx +762 -0
- package/src/components/waka-theme-manager/index.tsx +654 -0
- package/src/components/waka-thread-view/index.tsx +874 -0
- package/src/components/waka-tilt-card/index.tsx +250 -0
- package/src/components/waka-time-picker/index.tsx +479 -0
- package/src/components/waka-timeline/index.tsx +385 -0
- package/src/components/waka-tooltip-tour/index.tsx +855 -0
- package/src/components/waka-tour-guide/index.tsx +920 -0
- package/src/components/waka-tournament-bracket/index.tsx +1276 -0
- package/src/components/waka-tree/index.tsx +557 -0
- package/src/components/waka-treemap-chart/index.tsx +1031 -0
- package/src/components/waka-two-factor-setup/index.tsx +995 -0
- package/src/components/waka-typewriter/index.tsx +566 -0
- package/src/components/waka-typing-indicator/index.tsx +649 -0
- package/src/components/waka-versus-card/index.tsx +1026 -0
- package/src/components/waka-video/index.tsx +557 -0
- package/src/components/waka-video-call/index.tsx +1087 -0
- package/src/components/waka-virtual-list/index.tsx +327 -0
- package/src/components/waka-voice-message/index.tsx +1019 -0
- package/src/components/waka-welcome-modal/index.tsx +790 -0
- package/src/components/waka-xp-bar/index.tsx +799 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration des couleurs du thème
|
|
3
|
+
*/
|
|
4
|
+
export interface LoginColorConfig {
|
|
5
|
+
/** Couleur principale */
|
|
6
|
+
primary: string
|
|
7
|
+
/** Couleur secondaire */
|
|
8
|
+
secondary: string
|
|
9
|
+
/** Couleur d'accent */
|
|
10
|
+
accent: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration du thème
|
|
15
|
+
*/
|
|
16
|
+
export interface LoginThemeConfig {
|
|
17
|
+
/** Nom du thème */
|
|
18
|
+
name: string
|
|
19
|
+
/** Mode sombre activé */
|
|
20
|
+
dark_mode: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Assets (logos et images)
|
|
25
|
+
*/
|
|
26
|
+
export interface LoginAssetsConfig {
|
|
27
|
+
/** Logo du thème en mode sombre */
|
|
28
|
+
theme_logo_dark?: string
|
|
29
|
+
/** Logo du thème en mode clair */
|
|
30
|
+
theme_logo_light?: string
|
|
31
|
+
/** Image du thème en mode clair */
|
|
32
|
+
theme_image_light?: string
|
|
33
|
+
/** Image du thème en mode sombre */
|
|
34
|
+
theme_image_dark?: string
|
|
35
|
+
/** Image du sponsor en mode clair */
|
|
36
|
+
sponsor_image_light?: string
|
|
37
|
+
/** Image du sponsor en mode sombre */
|
|
38
|
+
sponsor_image_dark?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Options d'inscription et de connexion
|
|
43
|
+
*/
|
|
44
|
+
export interface LoginSignupOptions {
|
|
45
|
+
/** Autoriser la connexion classique */
|
|
46
|
+
allow_login: boolean
|
|
47
|
+
/** Requérir la MFA */
|
|
48
|
+
require_MFA: boolean
|
|
49
|
+
/** MFA par email */
|
|
50
|
+
MFA_email: boolean
|
|
51
|
+
/** MFA par WhatsApp */
|
|
52
|
+
MFA_whatsapp: boolean
|
|
53
|
+
/** MFA par RCS */
|
|
54
|
+
MFA_RCS: boolean
|
|
55
|
+
/** Autoriser SSO Google */
|
|
56
|
+
allow_sso_google: boolean
|
|
57
|
+
/** Autoriser SSO Microsoft */
|
|
58
|
+
allow_sso_microsoft: boolean
|
|
59
|
+
/** Autoriser SSO Apple */
|
|
60
|
+
allow_sso_apple: boolean
|
|
61
|
+
/** Autoriser SSO LinkedIn */
|
|
62
|
+
allow_sso_linkedIn: boolean
|
|
63
|
+
/** Autoriser SSO GitHub */
|
|
64
|
+
allow_sso_github: boolean
|
|
65
|
+
/** Autoriser SSO Facebook */
|
|
66
|
+
allow_sso_facebook: boolean
|
|
67
|
+
/** Autoriser SSO Instagram */
|
|
68
|
+
allow_sso_instagram: boolean
|
|
69
|
+
/** Autoriser SSO France Connect */
|
|
70
|
+
allow_sso_france_connect: boolean
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Configuration complète du composant Login
|
|
75
|
+
*
|
|
76
|
+
* Structure JSON attendue :
|
|
77
|
+
* {
|
|
78
|
+
* "color_json": {
|
|
79
|
+
* "primary": "#000000",
|
|
80
|
+
* "secondary": "#FFFFFF",
|
|
81
|
+
* "accent": "#FF9900"
|
|
82
|
+
* },
|
|
83
|
+
* "theme_json": {
|
|
84
|
+
* "name": "Default Theme",
|
|
85
|
+
* "dark_mode": true
|
|
86
|
+
* },
|
|
87
|
+
* "assets": {
|
|
88
|
+
* "theme_logo_dark": "https://...",
|
|
89
|
+
* "theme_logo_light": "https://...",
|
|
90
|
+
* "theme_image_light": "https://...",
|
|
91
|
+
* "theme_image_dark": "https://...",
|
|
92
|
+
* "sponsor_image_light": "https://...",
|
|
93
|
+
* "sponsor_image_dark": "https://..."
|
|
94
|
+
* },
|
|
95
|
+
* "waka_powered": true,
|
|
96
|
+
* "lang_code": "fr_FR",
|
|
97
|
+
* "signup_options": {
|
|
98
|
+
* "allow_login": true,
|
|
99
|
+
* "require_MFA": false,
|
|
100
|
+
* "MFA_email": true,
|
|
101
|
+
* "MFA_whatsapp": false,
|
|
102
|
+
* "MFA_RCS": false,
|
|
103
|
+
* "allow_sso_google": true,
|
|
104
|
+
* "allow_sso_microsoft": true,
|
|
105
|
+
* "allow_sso_apple": false,
|
|
106
|
+
* "allow_sso_linkedIn": false,
|
|
107
|
+
* "allow_sso_github": false,
|
|
108
|
+
* "allow_sso_facebook": false,
|
|
109
|
+
* "allow_sso_instagram": false,
|
|
110
|
+
* "allow_sso_france_connect": false
|
|
111
|
+
* },
|
|
112
|
+
* "oem_resolution_rules": ["..."]
|
|
113
|
+
* }
|
|
114
|
+
*/
|
|
115
|
+
export interface LoginConfig {
|
|
116
|
+
/** Configuration des couleurs du thème */
|
|
117
|
+
color_json: LoginColorConfig
|
|
118
|
+
/** Configuration du thème (nom et mode dark/light) */
|
|
119
|
+
theme_json: LoginThemeConfig
|
|
120
|
+
/** Assets (logos et images selon le thème) */
|
|
121
|
+
assets: LoginAssetsConfig
|
|
122
|
+
/** Afficher le badge "Waka Powered" en bas du formulaire */
|
|
123
|
+
waka_powered: boolean
|
|
124
|
+
/** Code de langue (ex: "fr_FR", "en_US") - utilisé pour l'i18n */
|
|
125
|
+
lang_code: string
|
|
126
|
+
/** Options d'inscription et de connexion (SSO, MFA, etc.) */
|
|
127
|
+
signup_options: LoginSignupOptions
|
|
128
|
+
/** Règles de résolution OEM (optionnel, utilisé pour la documentation/logique métier) */
|
|
129
|
+
oem_resolution_rules?: string[]
|
|
130
|
+
}
|
|
131
|
+
|
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { cn } from "../../utils"
|
|
5
|
+
import { Button } from "../../components/button"
|
|
6
|
+
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../../components/card"
|
|
7
|
+
import { Badge } from "../../components/badge"
|
|
8
|
+
import { Switch } from "../../components/switch"
|
|
9
|
+
import { Label } from "../../components/label"
|
|
10
|
+
import {
|
|
11
|
+
Check,
|
|
12
|
+
X,
|
|
13
|
+
Zap,
|
|
14
|
+
HelpCircle,
|
|
15
|
+
} from "lucide-react"
|
|
16
|
+
import {
|
|
17
|
+
Tooltip,
|
|
18
|
+
TooltipContent,
|
|
19
|
+
TooltipProvider,
|
|
20
|
+
TooltipTrigger,
|
|
21
|
+
} from "../../components/tooltip"
|
|
22
|
+
|
|
23
|
+
// ============================================
|
|
24
|
+
// TYPES
|
|
25
|
+
// ============================================
|
|
26
|
+
|
|
27
|
+
export interface PricingFeature {
|
|
28
|
+
name: string
|
|
29
|
+
included: boolean | "partial" | "limited"
|
|
30
|
+
tooltip?: string
|
|
31
|
+
value?: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface PricingPlan {
|
|
35
|
+
id: string
|
|
36
|
+
name: string
|
|
37
|
+
description?: string
|
|
38
|
+
price: number | string
|
|
39
|
+
priceYearly?: number | string
|
|
40
|
+
currency?: string
|
|
41
|
+
period?: string
|
|
42
|
+
periodYearly?: string
|
|
43
|
+
features: PricingFeature[]
|
|
44
|
+
buttonText?: string
|
|
45
|
+
buttonVariant?: "default" | "outline" | "secondary"
|
|
46
|
+
onSelect?: () => void
|
|
47
|
+
href?: string
|
|
48
|
+
popular?: boolean
|
|
49
|
+
badge?: string
|
|
50
|
+
disabled?: boolean
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface PricingFAQ {
|
|
54
|
+
question: string
|
|
55
|
+
answer: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface WakaPricingProps {
|
|
59
|
+
/** Titre */
|
|
60
|
+
title?: string
|
|
61
|
+
/** Description */
|
|
62
|
+
description?: string
|
|
63
|
+
/** Plans de tarification */
|
|
64
|
+
plans: PricingPlan[]
|
|
65
|
+
/** Afficher le toggle mensuel/annuel */
|
|
66
|
+
showBillingToggle?: boolean
|
|
67
|
+
/** Période de facturation */
|
|
68
|
+
billingPeriod?: "monthly" | "yearly"
|
|
69
|
+
/** Callback changement de période */
|
|
70
|
+
onBillingPeriodChange?: (period: "monthly" | "yearly") => void
|
|
71
|
+
/** Réduction annuelle (ex: "20%") */
|
|
72
|
+
yearlyDiscount?: string
|
|
73
|
+
/** FAQ */
|
|
74
|
+
faq?: PricingFAQ[]
|
|
75
|
+
/** Titre de la FAQ */
|
|
76
|
+
faqTitle?: string
|
|
77
|
+
/** Layout */
|
|
78
|
+
layout?: "cards" | "table"
|
|
79
|
+
/** Nombre de colonnes */
|
|
80
|
+
columns?: 2 | 3 | 4
|
|
81
|
+
/** Afficher la comparaison de features */
|
|
82
|
+
showComparison?: boolean
|
|
83
|
+
/** Classes CSS additionnelles */
|
|
84
|
+
className?: string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ============================================
|
|
88
|
+
// SUB-COMPONENTS
|
|
89
|
+
// ============================================
|
|
90
|
+
|
|
91
|
+
interface PricingToggleProps {
|
|
92
|
+
period: "monthly" | "yearly"
|
|
93
|
+
onChange: (period: "monthly" | "yearly") => void
|
|
94
|
+
yearlyDiscount?: string
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function PricingToggle({ period, onChange, yearlyDiscount }: PricingToggleProps) {
|
|
98
|
+
return (
|
|
99
|
+
<div className="flex items-center justify-center gap-4 mb-8">
|
|
100
|
+
<Label
|
|
101
|
+
htmlFor="billing-toggle"
|
|
102
|
+
className={cn(
|
|
103
|
+
"cursor-pointer transition-colors",
|
|
104
|
+
period === "monthly" ? "text-foreground" : "text-muted-foreground"
|
|
105
|
+
)}
|
|
106
|
+
>
|
|
107
|
+
Mensuel
|
|
108
|
+
</Label>
|
|
109
|
+
<Switch
|
|
110
|
+
id="billing-toggle"
|
|
111
|
+
checked={period === "yearly"}
|
|
112
|
+
onCheckedChange={(checked) => onChange(checked ? "yearly" : "monthly")}
|
|
113
|
+
/>
|
|
114
|
+
<Label
|
|
115
|
+
htmlFor="billing-toggle"
|
|
116
|
+
className={cn(
|
|
117
|
+
"cursor-pointer transition-colors flex items-center gap-2",
|
|
118
|
+
period === "yearly" ? "text-foreground" : "text-muted-foreground"
|
|
119
|
+
)}
|
|
120
|
+
>
|
|
121
|
+
Annuel
|
|
122
|
+
{yearlyDiscount && (
|
|
123
|
+
<Badge variant="secondary" className="text-xs">
|
|
124
|
+
-{yearlyDiscount}
|
|
125
|
+
</Badge>
|
|
126
|
+
)}
|
|
127
|
+
</Label>
|
|
128
|
+
</div>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
interface PricingCardProps {
|
|
133
|
+
plan: PricingPlan
|
|
134
|
+
billingPeriod: "monthly" | "yearly"
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function PricingCard({ plan, billingPeriod }: PricingCardProps) {
|
|
138
|
+
const price = billingPeriod === "yearly" && plan.priceYearly !== undefined
|
|
139
|
+
? plan.priceYearly
|
|
140
|
+
: plan.price
|
|
141
|
+
const period = billingPeriod === "yearly" && plan.periodYearly
|
|
142
|
+
? plan.periodYearly
|
|
143
|
+
: plan.period || "/mois"
|
|
144
|
+
|
|
145
|
+
const isCustomPrice = typeof price === "string"
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<Card
|
|
149
|
+
className={cn(
|
|
150
|
+
"relative flex flex-col",
|
|
151
|
+
plan.popular && "border-primary shadow-lg scale-105"
|
|
152
|
+
)}
|
|
153
|
+
>
|
|
154
|
+
{/* Popular badge */}
|
|
155
|
+
{plan.popular && (
|
|
156
|
+
<div className="absolute -top-3 left-1/2 -translate-x-1/2">
|
|
157
|
+
<Badge className="px-3">
|
|
158
|
+
<Zap className="h-3 w-3 mr-1" />
|
|
159
|
+
{plan.badge || "Populaire"}
|
|
160
|
+
</Badge>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
|
|
164
|
+
<CardHeader className="text-center pb-2">
|
|
165
|
+
<CardTitle className="text-xl">{plan.name}</CardTitle>
|
|
166
|
+
{plan.description && (
|
|
167
|
+
<CardDescription>{plan.description}</CardDescription>
|
|
168
|
+
)}
|
|
169
|
+
</CardHeader>
|
|
170
|
+
|
|
171
|
+
<CardContent className="flex-1">
|
|
172
|
+
{/* Price */}
|
|
173
|
+
<div className="text-center mb-6">
|
|
174
|
+
{isCustomPrice ? (
|
|
175
|
+
<div className="text-3xl font-bold">{price}</div>
|
|
176
|
+
) : (
|
|
177
|
+
<div className="flex items-baseline justify-center">
|
|
178
|
+
<span className="text-sm text-muted-foreground mr-1">
|
|
179
|
+
{plan.currency || "€"}
|
|
180
|
+
</span>
|
|
181
|
+
<span className="text-4xl font-bold">{price}</span>
|
|
182
|
+
<span className="text-sm text-muted-foreground ml-1">
|
|
183
|
+
{period}
|
|
184
|
+
</span>
|
|
185
|
+
</div>
|
|
186
|
+
)}
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
{/* Features */}
|
|
190
|
+
<ul className="space-y-3">
|
|
191
|
+
{plan.features.map((feature, index) => (
|
|
192
|
+
<li key={index} className="flex items-start gap-2">
|
|
193
|
+
{feature.included === true ? (
|
|
194
|
+
<Check className="h-5 w-5 text-green-500 flex-shrink-0" />
|
|
195
|
+
) : feature.included === "partial" || feature.included === "limited" ? (
|
|
196
|
+
<Check className="h-5 w-5 text-yellow-500 flex-shrink-0" />
|
|
197
|
+
) : (
|
|
198
|
+
<X className="h-5 w-5 text-muted-foreground flex-shrink-0" />
|
|
199
|
+
)}
|
|
200
|
+
<span
|
|
201
|
+
className={cn(
|
|
202
|
+
"text-sm",
|
|
203
|
+
!feature.included && "text-muted-foreground"
|
|
204
|
+
)}
|
|
205
|
+
>
|
|
206
|
+
{feature.name}
|
|
207
|
+
{feature.value && (
|
|
208
|
+
<span className="text-muted-foreground ml-1">
|
|
209
|
+
({feature.value})
|
|
210
|
+
</span>
|
|
211
|
+
)}
|
|
212
|
+
</span>
|
|
213
|
+
{feature.tooltip && (
|
|
214
|
+
<TooltipProvider>
|
|
215
|
+
<Tooltip>
|
|
216
|
+
<TooltipTrigger asChild>
|
|
217
|
+
<HelpCircle className="h-4 w-4 text-muted-foreground cursor-help" />
|
|
218
|
+
</TooltipTrigger>
|
|
219
|
+
<TooltipContent>
|
|
220
|
+
<p className="max-w-xs">{feature.tooltip}</p>
|
|
221
|
+
</TooltipContent>
|
|
222
|
+
</Tooltip>
|
|
223
|
+
</TooltipProvider>
|
|
224
|
+
)}
|
|
225
|
+
</li>
|
|
226
|
+
))}
|
|
227
|
+
</ul>
|
|
228
|
+
</CardContent>
|
|
229
|
+
|
|
230
|
+
<CardFooter>
|
|
231
|
+
<Button
|
|
232
|
+
className="w-full"
|
|
233
|
+
variant={plan.buttonVariant || (plan.popular ? "default" : "outline")}
|
|
234
|
+
onClick={plan.onSelect}
|
|
235
|
+
disabled={plan.disabled}
|
|
236
|
+
asChild={!!plan.href}
|
|
237
|
+
>
|
|
238
|
+
{plan.href ? (
|
|
239
|
+
<a href={plan.href}>{plan.buttonText || "Choisir"}</a>
|
|
240
|
+
) : (
|
|
241
|
+
plan.buttonText || "Choisir"
|
|
242
|
+
)}
|
|
243
|
+
</Button>
|
|
244
|
+
</CardFooter>
|
|
245
|
+
</Card>
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
interface PricingTableProps {
|
|
250
|
+
plans: PricingPlan[]
|
|
251
|
+
billingPeriod: "monthly" | "yearly"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function PricingTable({ plans, billingPeriod }: PricingTableProps) {
|
|
255
|
+
// Get all unique features
|
|
256
|
+
const allFeatures = Array.from(
|
|
257
|
+
new Set(plans.flatMap((plan) => plan.features.map((f) => f.name)))
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
return (
|
|
261
|
+
<div className="overflow-x-auto">
|
|
262
|
+
<table className="w-full border-collapse">
|
|
263
|
+
<thead>
|
|
264
|
+
<tr>
|
|
265
|
+
<th className="text-left p-4 border-b bg-muted/50">Fonctionnalité</th>
|
|
266
|
+
{plans.map((plan) => (
|
|
267
|
+
<th
|
|
268
|
+
key={plan.id}
|
|
269
|
+
className={cn(
|
|
270
|
+
"text-center p-4 border-b min-w-[150px]",
|
|
271
|
+
plan.popular && "bg-primary/5"
|
|
272
|
+
)}
|
|
273
|
+
>
|
|
274
|
+
<div className="font-bold">{plan.name}</div>
|
|
275
|
+
{plan.popular && (
|
|
276
|
+
<Badge className="mt-1" variant="default">
|
|
277
|
+
Populaire
|
|
278
|
+
</Badge>
|
|
279
|
+
)}
|
|
280
|
+
</th>
|
|
281
|
+
))}
|
|
282
|
+
</tr>
|
|
283
|
+
{/* Price row */}
|
|
284
|
+
<tr>
|
|
285
|
+
<td className="p-4 border-b bg-muted/50 font-medium">Prix</td>
|
|
286
|
+
{plans.map((plan) => {
|
|
287
|
+
const price = billingPeriod === "yearly" && plan.priceYearly !== undefined
|
|
288
|
+
? plan.priceYearly
|
|
289
|
+
: plan.price
|
|
290
|
+
const period = billingPeriod === "yearly" && plan.periodYearly
|
|
291
|
+
? plan.periodYearly
|
|
292
|
+
: plan.period || "/mois"
|
|
293
|
+
const isCustomPrice = typeof price === "string"
|
|
294
|
+
|
|
295
|
+
return (
|
|
296
|
+
<td
|
|
297
|
+
key={plan.id}
|
|
298
|
+
className={cn(
|
|
299
|
+
"text-center p-4 border-b",
|
|
300
|
+
plan.popular && "bg-primary/5"
|
|
301
|
+
)}
|
|
302
|
+
>
|
|
303
|
+
{isCustomPrice ? (
|
|
304
|
+
<span className="font-bold">{price}</span>
|
|
305
|
+
) : (
|
|
306
|
+
<span className="font-bold">
|
|
307
|
+
{plan.currency || "€"}{price}
|
|
308
|
+
<span className="text-sm font-normal text-muted-foreground">
|
|
309
|
+
{period}
|
|
310
|
+
</span>
|
|
311
|
+
</span>
|
|
312
|
+
)}
|
|
313
|
+
</td>
|
|
314
|
+
)
|
|
315
|
+
})}
|
|
316
|
+
</tr>
|
|
317
|
+
</thead>
|
|
318
|
+
<tbody>
|
|
319
|
+
{allFeatures.map((featureName, index) => (
|
|
320
|
+
<tr key={index} className={index % 2 === 0 ? "bg-muted/20" : ""}>
|
|
321
|
+
<td className="p-4 border-b">{featureName}</td>
|
|
322
|
+
{plans.map((plan) => {
|
|
323
|
+
const feature = plan.features.find((f) => f.name === featureName)
|
|
324
|
+
return (
|
|
325
|
+
<td
|
|
326
|
+
key={plan.id}
|
|
327
|
+
className={cn(
|
|
328
|
+
"text-center p-4 border-b",
|
|
329
|
+
plan.popular && "bg-primary/5"
|
|
330
|
+
)}
|
|
331
|
+
>
|
|
332
|
+
{feature ? (
|
|
333
|
+
feature.included === true ? (
|
|
334
|
+
feature.value ? (
|
|
335
|
+
<span>{feature.value}</span>
|
|
336
|
+
) : (
|
|
337
|
+
<Check className="h-5 w-5 text-green-500 mx-auto" />
|
|
338
|
+
)
|
|
339
|
+
) : feature.included === "partial" || feature.included === "limited" ? (
|
|
340
|
+
<span className="text-yellow-600">{feature.value || "Limité"}</span>
|
|
341
|
+
) : (
|
|
342
|
+
<X className="h-5 w-5 text-muted-foreground mx-auto" />
|
|
343
|
+
)
|
|
344
|
+
) : (
|
|
345
|
+
<X className="h-5 w-5 text-muted-foreground mx-auto" />
|
|
346
|
+
)}
|
|
347
|
+
</td>
|
|
348
|
+
)
|
|
349
|
+
})}
|
|
350
|
+
</tr>
|
|
351
|
+
))}
|
|
352
|
+
{/* Action row */}
|
|
353
|
+
<tr>
|
|
354
|
+
<td className="p-4"></td>
|
|
355
|
+
{plans.map((plan) => (
|
|
356
|
+
<td
|
|
357
|
+
key={plan.id}
|
|
358
|
+
className={cn(
|
|
359
|
+
"text-center p-4",
|
|
360
|
+
plan.popular && "bg-primary/5"
|
|
361
|
+
)}
|
|
362
|
+
>
|
|
363
|
+
<Button
|
|
364
|
+
variant={plan.buttonVariant || (plan.popular ? "default" : "outline")}
|
|
365
|
+
onClick={plan.onSelect}
|
|
366
|
+
disabled={plan.disabled}
|
|
367
|
+
asChild={!!plan.href}
|
|
368
|
+
>
|
|
369
|
+
{plan.href ? (
|
|
370
|
+
<a href={plan.href}>{plan.buttonText || "Choisir"}</a>
|
|
371
|
+
) : (
|
|
372
|
+
plan.buttonText || "Choisir"
|
|
373
|
+
)}
|
|
374
|
+
</Button>
|
|
375
|
+
</td>
|
|
376
|
+
))}
|
|
377
|
+
</tr>
|
|
378
|
+
</tbody>
|
|
379
|
+
</table>
|
|
380
|
+
</div>
|
|
381
|
+
)
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
interface PricingFAQSectionProps {
|
|
385
|
+
title?: string
|
|
386
|
+
items: PricingFAQ[]
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function PricingFAQSection({ title = "Questions fréquentes", items }: PricingFAQSectionProps) {
|
|
390
|
+
return (
|
|
391
|
+
<div className="mt-16">
|
|
392
|
+
<h2 className="text-2xl font-bold text-center mb-8">{title}</h2>
|
|
393
|
+
<div className="grid md:grid-cols-2 gap-6 max-w-4xl mx-auto">
|
|
394
|
+
{items.map((item, index) => (
|
|
395
|
+
<div key={index} className="space-y-2">
|
|
396
|
+
<h3 className="font-semibold">{item.question}</h3>
|
|
397
|
+
<p className="text-muted-foreground text-sm">{item.answer}</p>
|
|
398
|
+
</div>
|
|
399
|
+
))}
|
|
400
|
+
</div>
|
|
401
|
+
</div>
|
|
402
|
+
)
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// ============================================
|
|
406
|
+
// MAIN COMPONENT
|
|
407
|
+
// ============================================
|
|
408
|
+
|
|
409
|
+
export function WakaPricing({
|
|
410
|
+
title = "Tarification",
|
|
411
|
+
description,
|
|
412
|
+
plans,
|
|
413
|
+
showBillingToggle = true,
|
|
414
|
+
billingPeriod: externalBillingPeriod,
|
|
415
|
+
onBillingPeriodChange,
|
|
416
|
+
yearlyDiscount,
|
|
417
|
+
faq,
|
|
418
|
+
faqTitle,
|
|
419
|
+
layout = "cards",
|
|
420
|
+
columns = 3,
|
|
421
|
+
showComparison = false,
|
|
422
|
+
className,
|
|
423
|
+
}: WakaPricingProps) {
|
|
424
|
+
const [internalBillingPeriod, setInternalBillingPeriod] = React.useState<"monthly" | "yearly">("monthly")
|
|
425
|
+
|
|
426
|
+
const billingPeriod = externalBillingPeriod ?? internalBillingPeriod
|
|
427
|
+
|
|
428
|
+
const handleBillingPeriodChange = (period: "monthly" | "yearly") => {
|
|
429
|
+
if (onBillingPeriodChange) {
|
|
430
|
+
onBillingPeriodChange(period)
|
|
431
|
+
} else {
|
|
432
|
+
setInternalBillingPeriod(period)
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const columnClasses = {
|
|
437
|
+
2: "md:grid-cols-2",
|
|
438
|
+
3: "md:grid-cols-2 lg:grid-cols-3",
|
|
439
|
+
4: "md:grid-cols-2 lg:grid-cols-4",
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return (
|
|
443
|
+
<div className={cn("container py-16", className)}>
|
|
444
|
+
{/* Header */}
|
|
445
|
+
<div className="text-center mb-12">
|
|
446
|
+
<h1 className="text-3xl md:text-4xl font-bold tracking-tight mb-4">
|
|
447
|
+
{title}
|
|
448
|
+
</h1>
|
|
449
|
+
{description && (
|
|
450
|
+
<p className="text-lg text-muted-foreground max-w-2xl mx-auto">
|
|
451
|
+
{description}
|
|
452
|
+
</p>
|
|
453
|
+
)}
|
|
454
|
+
</div>
|
|
455
|
+
|
|
456
|
+
{/* Billing toggle */}
|
|
457
|
+
{showBillingToggle && (
|
|
458
|
+
<PricingToggle
|
|
459
|
+
period={billingPeriod}
|
|
460
|
+
onChange={handleBillingPeriodChange}
|
|
461
|
+
yearlyDiscount={yearlyDiscount}
|
|
462
|
+
/>
|
|
463
|
+
)}
|
|
464
|
+
|
|
465
|
+
{/* Plans */}
|
|
466
|
+
{layout === "cards" && !showComparison ? (
|
|
467
|
+
<div className={cn("grid gap-6 items-stretch", columnClasses[columns])}>
|
|
468
|
+
{plans.map((plan) => (
|
|
469
|
+
<PricingCard key={plan.id} plan={plan} billingPeriod={billingPeriod} />
|
|
470
|
+
))}
|
|
471
|
+
</div>
|
|
472
|
+
) : (
|
|
473
|
+
<PricingTable plans={plans} billingPeriod={billingPeriod} />
|
|
474
|
+
)}
|
|
475
|
+
|
|
476
|
+
{/* FAQ */}
|
|
477
|
+
{faq && faq.length > 0 && (
|
|
478
|
+
<PricingFAQSection title={faqTitle} items={faq} />
|
|
479
|
+
)}
|
|
480
|
+
</div>
|
|
481
|
+
)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ============================================
|
|
485
|
+
// PRESETS
|
|
486
|
+
// ============================================
|
|
487
|
+
|
|
488
|
+
export const defaultPricingPlans: PricingPlan[] = [
|
|
489
|
+
{
|
|
490
|
+
id: "free",
|
|
491
|
+
name: "Gratuit",
|
|
492
|
+
description: "Pour démarrer",
|
|
493
|
+
price: 0,
|
|
494
|
+
priceYearly: 0,
|
|
495
|
+
features: [
|
|
496
|
+
{ name: "1 utilisateur", included: true },
|
|
497
|
+
{ name: "5 projets", included: true },
|
|
498
|
+
{ name: "1 Go de stockage", included: true },
|
|
499
|
+
{ name: "Support email", included: true },
|
|
500
|
+
{ name: "API Access", included: false },
|
|
501
|
+
{ name: "Analytics avancés", included: false },
|
|
502
|
+
{ name: "Support prioritaire", included: false },
|
|
503
|
+
],
|
|
504
|
+
buttonText: "Commencer gratuitement",
|
|
505
|
+
buttonVariant: "outline",
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
id: "pro",
|
|
509
|
+
name: "Pro",
|
|
510
|
+
description: "Pour les équipes",
|
|
511
|
+
price: 29,
|
|
512
|
+
priceYearly: 24,
|
|
513
|
+
periodYearly: "/mois (facturé annuellement)",
|
|
514
|
+
popular: true,
|
|
515
|
+
features: [
|
|
516
|
+
{ name: "5 utilisateurs", included: true },
|
|
517
|
+
{ name: "Projets illimités", included: true },
|
|
518
|
+
{ name: "50 Go de stockage", included: true },
|
|
519
|
+
{ name: "Support email", included: true },
|
|
520
|
+
{ name: "API Access", included: true },
|
|
521
|
+
{ name: "Analytics avancés", included: true },
|
|
522
|
+
{ name: "Support prioritaire", included: false },
|
|
523
|
+
],
|
|
524
|
+
buttonText: "Essai gratuit 14 jours",
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
id: "enterprise",
|
|
528
|
+
name: "Enterprise",
|
|
529
|
+
description: "Pour les grandes équipes",
|
|
530
|
+
price: "Sur mesure",
|
|
531
|
+
features: [
|
|
532
|
+
{ name: "Utilisateurs illimités", included: true },
|
|
533
|
+
{ name: "Projets illimités", included: true },
|
|
534
|
+
{ name: "Stockage illimité", included: true },
|
|
535
|
+
{ name: "Support email", included: true },
|
|
536
|
+
{ name: "API Access", included: true },
|
|
537
|
+
{ name: "Analytics avancés", included: true },
|
|
538
|
+
{ name: "Support prioritaire", included: true },
|
|
539
|
+
],
|
|
540
|
+
buttonText: "Contacter les ventes",
|
|
541
|
+
buttonVariant: "outline",
|
|
542
|
+
},
|
|
543
|
+
]
|
|
544
|
+
|
|
545
|
+
export const defaultPricingFAQ: PricingFAQ[] = [
|
|
546
|
+
{
|
|
547
|
+
question: "Puis-je changer de plan à tout moment ?",
|
|
548
|
+
answer: "Oui, vous pouvez upgrader ou downgrader votre plan à tout moment. Les changements prennent effet immédiatement.",
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
question: "Y a-t-il une période d'essai ?",
|
|
552
|
+
answer: "Oui, tous nos plans payants incluent une période d'essai gratuite de 14 jours, sans carte bancaire requise.",
|
|
553
|
+
},
|
|
554
|
+
{
|
|
555
|
+
question: "Quels moyens de paiement acceptez-vous ?",
|
|
556
|
+
answer: "Nous acceptons les cartes de crédit (Visa, Mastercard, Amex), PayPal et les virements bancaires pour les entreprises.",
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
question: "Puis-je annuler à tout moment ?",
|
|
560
|
+
answer: "Absolument. Vous pouvez annuler votre abonnement à tout moment sans frais supplémentaires.",
|
|
561
|
+
},
|
|
562
|
+
]
|
|
563
|
+
|
|
564
|
+
export default WakaPricing
|