@zuii/booking 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ :root {
2
+ --booking-bg: var(--white);
3
+ --booking-color: var(--primary);
4
+ --booking-text: var(--booking-color);
5
+ --booking-selected-bg: #3c4e62;
6
+ --booking-selected-text: #fff;
7
+ --booking-footer-bg: #3c4e62;
8
+ --booking-footer-text: #fff;
9
+ --booking-radius: var(--radius-base);
10
+ --booking-gap: 1rem;
11
+ }
12
+
13
+ .booking-wrapper {
14
+ display: flex;
15
+ gap: var(--booking-gap);
16
+ flex-wrap: wrap;
17
+ }
18
+
19
+ .booking__calendar-column {
20
+ flex: 1;
21
+ max-width: 100%;
22
+ }
23
+ @media (max-width: 450px) {
24
+ .booking__calendar-column {
25
+ width: 100%;
26
+ }
27
+ }
28
+
29
+ .booking__slots-column {
30
+ flex: 1;
31
+ }
32
+
33
+ .booking {
34
+ width: 100%;
35
+ border-radius: var(--booking-radius);
36
+ overflow: hidden;
37
+ color: var(--booking-text);
38
+ user-select: none;
39
+ display: flex;
40
+ flex-direction: column;
41
+ height: 100%;
42
+ }
43
+
44
+ .booking--empty {
45
+ display: flex;
46
+ flex-direction: column;
47
+ height: 100%;
48
+ justify-content: center;
49
+ align-items: center;
50
+ background: var(--booking-bg);
51
+ border: 1px dashed var(--booking-color);
52
+ border-radius: var(--booking-radius);
53
+ }
54
+
55
+ .booking__empty-message {
56
+ text-align: center;
57
+ color: #94a3b8;
58
+ padding: 40px;
59
+ }
60
+ .booking__empty-message svg {
61
+ width: 48px;
62
+ height: 48px;
63
+ margin-bottom: 16px;
64
+ opacity: 0.5;
65
+ }
66
+ .booking__empty-message p {
67
+ font-size: 16px;
68
+ margin: 0;
69
+ }
70
+
71
+ .booking__slots {
72
+ display: grid;
73
+ grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
74
+ gap: 15px;
75
+ }
76
+
77
+ .booking__slot {
78
+ background: var(--booking-bg);
79
+ padding: 20px 10px;
80
+ border: none;
81
+ border-radius: 4px;
82
+ text-align: center;
83
+ cursor: pointer;
84
+ font-weight: 700;
85
+ font-size: 20px;
86
+ color: var(--booking-text);
87
+ transition: all 0.2s;
88
+ }
89
+ .booking__slot:hover {
90
+ background: color-mix(in srgb, var(--booking-bg), #000 5%);
91
+ }
92
+
93
+ .booking__slot--selected {
94
+ background: var(--booking-selected-bg);
95
+ color: var(--booking-selected-text);
96
+ }
97
+
98
+ .booking__slot--range {
99
+ background: color-mix(in srgb, var(--booking-selected-bg), transparent 60%);
100
+ color: var(--booking-selected-text);
101
+ }
102
+
103
+ .booking__footer {
104
+ background: var(--booking-footer-bg);
105
+ color: var(--booking-footer-text);
106
+ padding: 25px;
107
+ border-radius: 4px;
108
+ text-align: left;
109
+ font-size: 22px;
110
+ font-weight: 400;
111
+ line-height: 1.4;
112
+ }
113
+
114
+ .booking__empty {
115
+ color: #6c757d;
116
+ font-style: italic;
117
+ }
118
+
119
+ .booking__title {
120
+ font-size: 1.2rem;
121
+ color: var(--booking-text);
122
+ }
123
+
124
+ /*# sourceMappingURL=booking.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["../../src/style/_booking.scss","../../src/style/_booking-empty-message.scss","../../src/style/_booking-slots.scss","../../src/style/_booking-slot.scss","../../src/style/_booking-footer.scss","../../src/style/_booking-empty.scss","../../src/style/_booking-title.scss"],"names":[],"mappings":"AAAA;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;;;AAKD;EACC;EAEA;;AAEA;EALD;IAME;;;;AAIF;EACC;;;AAKD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACvDD;EACC;EACA;EACA;;AAEA;EACC;EACA;EACA;EACA;;AAGD;EACC;EACA;;;ACdF;EACC;EACA;EACA;;;ACHD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACC;;;AAIF;EACC;EACA;;;AAGD;EACC;EACA;;;ACxBD;EACC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;ACRD;EACC;EACA;;;ACFD;EACC;EACA","file":"booking.css"}
@@ -0,0 +1 @@
1
+ :root{--booking-bg: var(--white);--booking-color: var(--primary);--booking-text: var(--booking-color);--booking-selected-bg: #3c4e62;--booking-selected-text: #fff;--booking-footer-bg: #3c4e62;--booking-footer-text: #fff;--booking-radius: var(--radius-base);--booking-gap: 1rem}.booking-wrapper{display:flex;gap:var(--booking-gap);flex-wrap:wrap}.booking__calendar-column{flex:1;max-width:100%}@media(max-width: 450px){.booking__calendar-column{width:100%}}.booking__slots-column{flex:1}.booking{width:100%;border-radius:var(--booking-radius);overflow:hidden;color:var(--booking-text);user-select:none;display:flex;flex-direction:column;height:100%}.booking--empty{display:flex;flex-direction:column;height:100%;justify-content:center;align-items:center;background:var(--booking-bg);border:1px dashed var(--booking-color);border-radius:var(--booking-radius)}.booking__empty-message{text-align:center;color:#94a3b8;padding:40px}.booking__empty-message svg{width:48px;height:48px;margin-bottom:16px;opacity:.5}.booking__empty-message p{font-size:16px;margin:0}.booking__slots{display:grid;grid-template-columns:repeat(auto-fill, minmax(130px, 1fr));gap:15px}.booking__slot{background:var(--booking-bg);padding:20px 10px;border:none;border-radius:4px;text-align:center;cursor:pointer;font-weight:700;font-size:20px;color:var(--booking-text);transition:all .2s}.booking__slot:hover{background:color-mix(in srgb, var(--booking-bg), #000 5%)}.booking__slot--selected{background:var(--booking-selected-bg);color:var(--booking-selected-text)}.booking__slot--range{background:color-mix(in srgb, var(--booking-selected-bg), transparent 60%);color:var(--booking-selected-text)}.booking__footer{background:var(--booking-footer-bg);color:var(--booking-footer-text);padding:25px;border-radius:4px;text-align:left;font-size:22px;font-weight:400;line-height:1.4}.booking__empty{color:#6c757d;font-style:italic}.booking__title{font-size:1.2rem;color:var(--booking-text)}/*# sourceMappingURL=booking.min.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sourceRoot":"","sources":["../../src/style/_booking.scss","../../src/style/_booking-empty-message.scss","../../src/style/_booking-slots.scss","../../src/style/_booking-slot.scss","../../src/style/_booking-footer.scss","../../src/style/_booking-empty.scss","../../src/style/_booking-title.scss"],"names":[],"mappings":"AAAA,MACC,2BACA,gCACA,qCACA,+BACA,8BACA,6BACA,4BACA,qCACA,oBAGD,iBACC,aACA,uBACA,eAKD,0BACC,OAEA,eAEA,yBALD,0BAME,YAIF,uBACC,OAKD,SACC,WACA,oCACA,gBACA,0BACA,iBACA,aACA,sBACA,YAGD,gBACC,aACA,sBACA,YACA,uBACA,mBACA,6BACA,uCACA,oCCvDD,wBACC,kBACA,cACA,aAEA,4BACC,WACA,YACA,mBACA,WAGD,0BACC,eACA,SCdF,gBACC,aACA,4DACA,SCHD,eACC,6BACA,kBACA,YACA,kBACA,kBACA,eACA,gBACA,eACA,0BACA,mBAEA,qBACC,0DAIF,yBACC,sCACA,mCAGD,sBACC,2EACA,mCCxBD,iBACC,oCACA,iCACA,aACA,kBACA,gBACA,eACA,gBACA,gBCRD,gBACC,cACA,kBCFD,gBACC,iBACA","file":"booking.min.css"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@zuii/booking",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "description": "Composant Booking pour zuii",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "src/symfony"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ },
19
+ "./react": {
20
+ "types": "./dist/react/index.d.ts",
21
+ "import": "./dist/react/index.js",
22
+ "require": "./dist/react/index.cjs"
23
+ },
24
+ "./symfony": "./src/symfony/booking_controller.ts",
25
+ "./style": "./dist/style/booking.css"
26
+ },
27
+ "dependencies": {
28
+ "date-fns": "^4.1.0",
29
+ "@zuii/calendar": "0.1.1"
30
+ },
31
+ "peerDependencies": {
32
+ "react": ">=16.8.0",
33
+ "@zuii/core": "1.0.0"
34
+ },
35
+ "keywords": [
36
+ "zuii",
37
+ "booking",
38
+ "reservation"
39
+ ],
40
+ "author": "Vincent Moreau",
41
+ "license": "MIT",
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "scripts": {
46
+ "build": "pnpm build:js && pnpm build:css && pnpm build:css:min",
47
+ "build:css": "sass src/style/index.scss dist/style/booking.css --load-path=node_modules --silence-deprecation=import",
48
+ "build:css:min": "sass src/style/index.scss dist/style/booking.min.css --style=compressed --load-path=node_modules --silence-deprecation=import",
49
+ "build:js": "tsup",
50
+ "dev": "pnpm build:js && pnpm build:css && tsup --watch"
51
+ }
52
+ }
@@ -0,0 +1,40 @@
1
+ # Intégration Symfony pour @zuii/booking
2
+
3
+ Ce dossier contient le contrôleur Stimulus pour utiliser l'interface de réservation dans un projet Symfony.
4
+
5
+ ## Installation
6
+
7
+ Assurez-vous d'avoir installé le package via npm/pnpm :
8
+ ```bash
9
+ pnpm add @zuii/booking @zuii/calendar
10
+ ```
11
+
12
+ ## Utilisation
13
+
14
+ ### 1. Enregistrement du contrôleur
15
+ Dans votre fichier `assets/controllers.json`, importez le contrôleur :
16
+
17
+ ```javascript
18
+ import BookingController from '@zuii/booking/symfony';
19
+ // ... enregistrement dans Stimulus
20
+ ```
21
+
22
+ ### 2. Utilisation dans Twig
23
+ ```twig
24
+ <div {{ stimulus_controller('@zuii/booking/symfony', {
25
+ lang: 'fr',
26
+ availability: { '2026-04-02': ['10:00', '11:00', '13:00'] },
27
+ fields: [
28
+ { name: 'full_name', label: 'Nom complet', type: 'text', required: true },
29
+ { name: 'email', label: 'Email', type: 'email', required: true }
30
+ ],
31
+ inputName: 'reservation'
32
+ }) }}></div>
33
+
34
+ <script>
35
+ document.addEventListener('booking:slot-select', (event) => {
36
+ console.log('Réservation confirmée :', event.detail);
37
+ // event.detail contient : { date, slot, formData }
38
+ });
39
+ </script>
40
+ ```
@@ -0,0 +1,72 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { Booking } from '../js/Booking';
3
+
4
+ /**
5
+ * Stimulus controller for @zuii/booking.
6
+ *
7
+ * Usage in Twig:
8
+ * <div {{ stimulus_controller('@zuii/booking/symfony', {
9
+ * lang: 'fr',
10
+ * availability: { '2026-04-02': ['10:00', '11:00'] },
11
+ * fields: [
12
+ * { name: 'name', label: 'Nom', type: 'text', required: true }
13
+ * ]
14
+ * }) }}></div>
15
+ */
16
+ export default class extends Controller {
17
+ static values = {
18
+ lang: { type: String, default: 'fr' },
19
+ availability: { type: Object, default: {} },
20
+ selectedDate: String,
21
+ inputName: { type: String, default: 'booking_datetime' },
22
+ fields: { type: Array, default: [] },
23
+ mode: { type: String, default: 'single' },
24
+ disablePast: { type: Boolean, default: false },
25
+ initialDate: String
26
+ };
27
+
28
+ declare langValue: 'fr' | 'en';
29
+ declare availabilityValue: Record<string, string[]>;
30
+ declare selectedDateValue: string;
31
+ declare inputNameValue: string;
32
+ declare fieldsValue: any[];
33
+ declare modeValue: 'single' | 'range';
34
+ declare disablePastValue: boolean;
35
+ declare initialDateValue: string;
36
+
37
+ private booking: Booking | null = null;
38
+
39
+ connect() {
40
+ const options: any = {
41
+ lang: this.langValue,
42
+ availability: this.availabilityValue,
43
+ inputName: this.inputNameValue,
44
+ mode: this.modeValue,
45
+ disablePast: this.disablePastValue,
46
+ onSlotSelect: (date: Date, slot: string, formData: any) => {
47
+ this.dispatch('slot-select', { detail: { date, slot, formData } });
48
+ }
49
+ };
50
+
51
+ if (this.selectedDateValue) {
52
+ options.selectedDate = new Date(this.selectedDateValue);
53
+ }
54
+ if (this.initialDateValue) {
55
+ options.initialDate = new Date(this.initialDateValue);
56
+ }
57
+ if (this.fieldsValue && this.fieldsValue.length > 0) {
58
+ options.fields = this.fieldsValue;
59
+ }
60
+
61
+ this.booking = new Booking(this.element as HTMLElement, options);
62
+ }
63
+
64
+ /**
65
+ * Callback Stimulus quand la langue change dynamiquement.
66
+ */
67
+ langValueChanged() {
68
+ if (this.booking) {
69
+ this.booking.setLanguage(this.langValue);
70
+ }
71
+ }
72
+ }