@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.
- package/LICENSE +21 -0
- package/dist/index.cjs +94 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +66 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +94 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.cjs +94 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +15 -0
- package/dist/react/index.d.ts +15 -0
- package/dist/react/index.js +94 -0
- package/dist/react/index.js.map +1 -0
- package/dist/style/booking.css +124 -0
- package/dist/style/booking.css.map +1 -0
- package/dist/style/booking.min.css +1 -0
- package/dist/style/booking.min.css.map +1 -0
- package/package.json +52 -0
- package/src/symfony/README.md +40 -0
- package/src/symfony/booking_controller.ts +72 -0
|
@@ -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
|
+
}
|