@autocode-cli/autocode 0.22.0 → 0.23.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.
Files changed (157) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/_nuxt/{DFQ30pd7.js → 4sw7JTbp.js} +1 -1
  3. package/.output/public/_nuxt/{BvF9_V7p.js → B6pOO9Bz.js} +1 -1
  4. package/.output/public/_nuxt/{DBuWa6JT.js → BAAVMorC.js} +1 -1
  5. package/.output/public/_nuxt/{BBgAVlXU.js → BJ-MtkWm.js} +1 -1
  6. package/.output/public/_nuxt/{CWENDdnZ.js → BJz8iexS.js} +1 -1
  7. package/.output/public/_nuxt/{DykwyQae.js → BMCm0zjc.js} +1 -1
  8. package/.output/public/_nuxt/{BvUbqlcZ.js → BU6KT1Jg.js} +1 -1
  9. package/.output/public/_nuxt/{FIIaIpPb.js → BXorvbPI.js} +1 -1
  10. package/.output/public/_nuxt/{DwfwVH0w.js → BdgB0Sk8.js} +1 -1
  11. package/.output/public/_nuxt/{QtPIr4OQ.js → BiqphZN8.js} +1 -1
  12. package/.output/public/_nuxt/{Bsd2P-Xc.js → Bn2y2u4i.js} +1 -1
  13. package/.output/public/_nuxt/{Bu1Qq2g-.js → BtXQIoy8.js} +1 -1
  14. package/.output/public/_nuxt/{DRo5NaOZ.js → Byshfb8L.js} +1 -1
  15. package/.output/public/_nuxt/{D8RlVVzC.js → C10TWEVH.js} +1 -1
  16. package/.output/public/_nuxt/{DU0awelf.js → C2rmiAJ1.js} +1 -1
  17. package/.output/public/_nuxt/{Zzp33YZj.js → CMIuQb6D.js} +1 -1
  18. package/.output/public/_nuxt/{jYigECdj.js → CTbIP459.js} +1 -1
  19. package/.output/public/_nuxt/{D4lcVP-d.js → ClY4a-PO.js} +1 -1
  20. package/.output/public/_nuxt/{CjVJcaTo.js → D0HHOq4k.js} +3 -3
  21. package/.output/public/_nuxt/{DYYF8rpr.js → D1JH-OfY.js} +1 -1
  22. package/.output/public/_nuxt/{Bxcwuw3U.js → D9fas07B.js} +1 -1
  23. package/.output/public/_nuxt/{DaYBQX26.js → DAd8dbng.js} +1 -1
  24. package/.output/public/_nuxt/{iHS1jy-1.js → DNMLSDtV.js} +1 -1
  25. package/.output/public/_nuxt/{_HJO0SwU.js → DbZiOpag.js} +1 -1
  26. package/.output/public/_nuxt/{TB1o0NrH.js → DuqM_LGj.js} +1 -1
  27. package/.output/public/_nuxt/{CoGBQbLh.js → DxFm2Qrx.js} +1 -1
  28. package/.output/public/_nuxt/builds/latest.json +1 -1
  29. package/.output/public/_nuxt/builds/meta/35ace9c2-472c-4755-ae87-74fdb84336dd.json +1 -0
  30. package/.output/public/_nuxt/{BZUmpBmU.js → c4NRZ8AG.js} +1 -1
  31. package/.output/public/_nuxt/{BthlfLoK.js → g7WOzF8b.js} +1 -1
  32. package/.output/public/_nuxt/{TA-NBooC.js → kNuGsBnB.js} +1 -1
  33. package/.output/public/_nuxt/{DNUcHFTN.js → kZiZQgsI.js} +1 -1
  34. package/.output/public/_nuxt/{CTV7-Iux.js → mty-mFWB.js} +1 -1
  35. package/.output/public/_payload.json +1 -1
  36. package/.output/public/fake-features/cocktail-generator/cocktails.js +541 -0
  37. package/.output/public/fake-features/cocktail-generator/index.html +620 -0
  38. package/.output/public/index.html +1 -1
  39. package/.output/server/chunks/build/_name_-UJA12Rs2.mjs +1 -1
  40. package/.output/server/chunks/build/client.precomputed.mjs +1 -1
  41. package/.output/server/chunks/build/fetch-B5NxMLIO.mjs +1 -1
  42. package/.output/server/chunks/build/nuxt-link-Cq8xZgFP.mjs +1 -1
  43. package/.output/server/chunks/build/server.mjs +3 -3
  44. package/.output/server/chunks/build/styles.mjs +7 -7
  45. package/.output/server/chunks/build/usePipeline-ZPHbtOs6.mjs +1 -1
  46. package/.output/server/chunks/nitro/nitro.mjs +802 -379
  47. package/.output/server/chunks/nitro/nitro.mjs.map +1 -1
  48. package/.output/server/chunks/routes/_ws.mjs +1 -1
  49. package/.output/server/chunks/routes/api/index.get2.mjs +6 -2
  50. package/.output/server/chunks/routes/api/index.get2.mjs.map +1 -1
  51. package/.output/server/chunks/routes/api/index.get3.mjs +1 -1
  52. package/.output/server/chunks/routes/api/index.get4.mjs +1 -1
  53. package/.output/server/chunks/routes/api/index.post2.mjs +1 -1
  54. package/.output/server/chunks/routes/api/index.post3.mjs +1 -1
  55. package/.output/server/chunks/routes/api/issues/_id/comments.get.mjs +1 -2
  56. package/.output/server/chunks/routes/api/issues/_id/comments.get.mjs.map +1 -1
  57. package/.output/server/chunks/routes/api/issues/_id/comments.post.mjs +1 -2
  58. package/.output/server/chunks/routes/api/issues/_id/comments.post.mjs.map +1 -1
  59. package/.output/server/chunks/routes/api/issues/_id/full-history.get.mjs +1 -1
  60. package/.output/server/chunks/routes/api/issues/_id/full-terminal.get.mjs +1 -1
  61. package/.output/server/chunks/routes/api/issues/_id/history/_sessionId/log.get.mjs +1 -1
  62. package/.output/server/chunks/routes/api/issues/_id/history/_sessionId/prompt.get.mjs +1 -1
  63. package/.output/server/chunks/routes/api/issues/_id/history.get.mjs +1 -1
  64. package/.output/server/chunks/routes/api/issues/_id/log.get.mjs +1 -1
  65. package/.output/server/chunks/routes/api/issues/_id/move.post.mjs +1 -1
  66. package/.output/server/chunks/routes/api/issues/_id/next.post.mjs +1 -1
  67. package/.output/server/chunks/routes/api/issues/actionable.get.mjs +1 -1
  68. package/.output/server/chunks/routes/api/issues/autocomplete.post.mjs +1 -1
  69. package/.output/server/chunks/routes/api/issues/graph.get.mjs +1 -1
  70. package/.output/server/chunks/routes/api/pipelines/_name/activate.put.mjs +1 -1
  71. package/.output/server/chunks/routes/api/pipelines/_name/versions/_version/activate.put.mjs +1 -1
  72. package/.output/server/chunks/routes/api/pipelines/_name/versions/_version/finalize.post.mjs +1 -1
  73. package/.output/server/chunks/routes/api/pipelines/_name/versions/_version_.delete.mjs +1 -1
  74. package/.output/server/chunks/routes/api/pipelines/_name/versions/_version_.get.mjs +1 -1
  75. package/.output/server/chunks/routes/api/pipelines/_name/versions/_version_.put.mjs +1 -1
  76. package/.output/server/chunks/routes/api/pipelines/_name/versions.get.mjs +1 -1
  77. package/.output/server/chunks/routes/api/pipelines/_name/versions.post.mjs +1 -1
  78. package/.output/server/chunks/routes/api/pipelines/_name_.delete.mjs +1 -1
  79. package/.output/server/chunks/routes/api/pipelines/_name_.get.mjs +1 -1
  80. package/.output/server/chunks/routes/api/pipelines/_name_.put.mjs +1 -1
  81. package/.output/server/chunks/routes/api/stats.get.mjs +1 -1
  82. package/.output/server/chunks/routes/api/workflow/health.get.mjs +1 -1
  83. package/.output/server/chunks/routes/api/ws/status.get.mjs +1 -1
  84. package/.output/server/chunks/routes/renderer.mjs +1 -1
  85. package/.output/server/index.mjs +1 -1
  86. package/.output/server/node_modules/.prisma/client/index.js +6 -3
  87. package/.output/server/node_modules/.prisma/client/package.json +1 -1
  88. package/.output/server/package.json +1 -1
  89. package/bin/autocode +50 -0
  90. package/package.json +1 -1
  91. package/templates/prompts/_transition-decision.en.md +69 -0
  92. package/templates/prompts/_transition-decision.fr.md +69 -0
  93. package/templates/prompts/backlog.en.md +1 -3
  94. package/templates/prompts/backlog.fr.md +1 -3
  95. package/templates/prompts/changelog.en.md +1 -4
  96. package/templates/prompts/changelog.fr.md +1 -4
  97. package/templates/prompts/deploy-prod.en.md +1 -4
  98. package/templates/prompts/deploy-prod.fr.md +1 -4
  99. package/templates/prompts/deploy-staging.en.md +1 -4
  100. package/templates/prompts/deploy-staging.fr.md +1 -4
  101. package/templates/prompts/design.en.md +1 -4
  102. package/templates/prompts/design.fr.md +1 -4
  103. package/templates/prompts/dev.en.md +1 -4
  104. package/templates/prompts/dev.fr.md +1 -4
  105. package/templates/prompts/done.en.md +2 -3
  106. package/templates/prompts/done.fr.md +2 -3
  107. package/templates/prompts/git-commit.en.md +1 -4
  108. package/templates/prompts/git-commit.fr.md +1 -4
  109. package/templates/prompts/git-push.en.md +1 -4
  110. package/templates/prompts/git-push.fr.md +1 -4
  111. package/templates/prompts/git-tag.en.md +1 -4
  112. package/templates/prompts/git-tag.fr.md +1 -4
  113. package/templates/prompts/in-progress.en.md +2 -8
  114. package/templates/prompts/in-progress.fr.md +1 -7
  115. package/templates/prompts/qualification.en.md +1 -4
  116. package/templates/prompts/qualification.fr.md +0 -3
  117. package/templates/prompts/ready.en.md +3 -6
  118. package/templates/prompts/ready.fr.md +3 -6
  119. package/templates/prompts/retest-cypress.en.md +1 -4
  120. package/templates/prompts/retest-cypress.fr.md +1 -4
  121. package/templates/prompts/retest-playwright.en.md +1 -4
  122. package/templates/prompts/retest-playwright.fr.md +1 -4
  123. package/templates/prompts/retest-unit.en.md +1 -4
  124. package/templates/prompts/retest-unit.fr.md +1 -4
  125. package/templates/prompts/retest.en.md +1 -4
  126. package/templates/prompts/retest.fr.md +1 -4
  127. package/templates/prompts/review-best-practices.en.md +1 -4
  128. package/templates/prompts/review-best-practices.fr.md +1 -4
  129. package/templates/prompts/review-code.en.md +1 -4
  130. package/templates/prompts/review-code.fr.md +1 -4
  131. package/templates/prompts/review-consistency.en.md +1 -4
  132. package/templates/prompts/review-consistency.fr.md +1 -4
  133. package/templates/prompts/review-no-duplication.en.md +1 -4
  134. package/templates/prompts/review-no-duplication.fr.md +1 -4
  135. package/templates/prompts/review-security.en.md +1 -4
  136. package/templates/prompts/review-security.fr.md +1 -4
  137. package/templates/prompts/specification.en.md +1 -4
  138. package/templates/prompts/specification.fr.md +1 -4
  139. package/templates/prompts/splitter.en.md +1 -4
  140. package/templates/prompts/splitter.fr.md +0 -3
  141. package/templates/prompts/testing-cypress.en.md +1 -4
  142. package/templates/prompts/testing-cypress.fr.md +1 -4
  143. package/templates/prompts/testing-integration.en.md +1 -4
  144. package/templates/prompts/testing-integration.fr.md +1 -4
  145. package/templates/prompts/testing-playwright.en.md +1 -4
  146. package/templates/prompts/testing-playwright.fr.md +1 -4
  147. package/templates/prompts/testing-unit.en.md +1 -4
  148. package/templates/prompts/testing-unit.fr.md +1 -4
  149. package/templates/prompts/update-docs.en.md +1 -4
  150. package/templates/prompts/update-docs.fr.md +1 -4
  151. package/templates/prompts/validate-staging.en.md +1 -4
  152. package/templates/prompts/validate-staging.fr.md +1 -4
  153. package/.output/public/_nuxt/builds/meta/83d9a3fc-c99e-4e26-adef-e7f5b329b81a.json +0 -1
  154. package/.output/server/chunks/_/comments.service.mjs +0 -26
  155. package/.output/server/chunks/_/comments.service.mjs.map +0 -1
  156. /package/.output/public/_i18n/{zP5M_e1m → __ad3z6g}/en/messages.json +0 -0
  157. /package/.output/public/_i18n/{zP5M_e1m → __ad3z6g}/fr/messages.json +0 -0
@@ -0,0 +1,620 @@
1
+ <!DOCTYPE html>
2
+ <html lang="fr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Générateur de Cocktails Aléatoires</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ min-height: 100vh;
18
+ padding: 20px;
19
+ }
20
+
21
+ .container {
22
+ max-width: 900px;
23
+ margin: 0 auto;
24
+ }
25
+
26
+ header {
27
+ text-align: center;
28
+ color: white;
29
+ margin-bottom: 30px;
30
+ }
31
+
32
+ header h1 {
33
+ font-size: 2.5rem;
34
+ margin-bottom: 10px;
35
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
36
+ }
37
+
38
+ header p {
39
+ font-size: 1.1rem;
40
+ opacity: 0.9;
41
+ }
42
+
43
+ /* Filtres */
44
+ .filters-container {
45
+ background: white;
46
+ border-radius: 12px;
47
+ padding: 20px;
48
+ margin-bottom: 25px;
49
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
50
+ }
51
+
52
+ .filters-title {
53
+ font-size: 1rem;
54
+ color: #666;
55
+ margin-bottom: 12px;
56
+ }
57
+
58
+ .filters {
59
+ display: flex;
60
+ flex-wrap: wrap;
61
+ gap: 10px;
62
+ }
63
+
64
+ .filter-btn {
65
+ padding: 10px 18px;
66
+ border: 2px solid #e0e0e0;
67
+ background: white;
68
+ border-radius: 25px;
69
+ cursor: pointer;
70
+ font-size: 0.9rem;
71
+ transition: all 0.3s ease;
72
+ color: #555;
73
+ }
74
+
75
+ .filter-btn:hover {
76
+ border-color: #667eea;
77
+ color: #667eea;
78
+ }
79
+
80
+ .filter-btn.active {
81
+ background: #667eea;
82
+ border-color: #667eea;
83
+ color: white;
84
+ }
85
+
86
+ /* Carte cocktail */
87
+ .cocktail-card {
88
+ background: white;
89
+ border-radius: 16px;
90
+ padding: 30px;
91
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.15);
92
+ transition: transform 0.3s ease;
93
+ }
94
+
95
+ .cocktail-card.loading {
96
+ opacity: 0.7;
97
+ transform: scale(0.98);
98
+ }
99
+
100
+ .cocktail-header {
101
+ display: flex;
102
+ justify-content: space-between;
103
+ align-items: flex-start;
104
+ margin-bottom: 25px;
105
+ flex-wrap: wrap;
106
+ gap: 15px;
107
+ }
108
+
109
+ .cocktail-title-section {
110
+ flex: 1;
111
+ }
112
+
113
+ .cocktail-name {
114
+ font-size: 2rem;
115
+ color: #333;
116
+ margin-bottom: 8px;
117
+ }
118
+
119
+ .cocktail-meta {
120
+ display: flex;
121
+ align-items: center;
122
+ gap: 15px;
123
+ flex-wrap: wrap;
124
+ }
125
+
126
+ .cocktail-badge {
127
+ display: inline-block;
128
+ padding: 6px 14px;
129
+ border-radius: 20px;
130
+ font-size: 0.85rem;
131
+ font-weight: 600;
132
+ }
133
+
134
+ .badge-alcoholic {
135
+ background: #ffeaa7;
136
+ color: #b8860b;
137
+ }
138
+
139
+ .badge-non-alcoholic {
140
+ background: #81ecec;
141
+ color: #00838f;
142
+ }
143
+
144
+ .cocktail-base {
145
+ color: #666;
146
+ font-size: 0.95rem;
147
+ }
148
+
149
+ /* Section verre avec icône */
150
+ .glass-section {
151
+ text-align: center;
152
+ min-width: 100px;
153
+ }
154
+
155
+ .glass-icon {
156
+ font-size: 4rem;
157
+ margin-bottom: 8px;
158
+ }
159
+
160
+ .glass-name {
161
+ font-size: 0.9rem;
162
+ color: #666;
163
+ font-weight: 500;
164
+ }
165
+
166
+ /* Sections ingrédients et instructions */
167
+ .cocktail-content {
168
+ display: grid;
169
+ grid-template-columns: 1fr 1fr;
170
+ gap: 30px;
171
+ margin-top: 25px;
172
+ }
173
+
174
+ @media (max-width: 768px) {
175
+ .cocktail-content {
176
+ grid-template-columns: 1fr;
177
+ }
178
+ }
179
+
180
+ .section-title {
181
+ font-size: 1.2rem;
182
+ color: #667eea;
183
+ margin-bottom: 15px;
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 8px;
187
+ }
188
+
189
+ .section-title::before {
190
+ content: '';
191
+ width: 4px;
192
+ height: 20px;
193
+ background: #667eea;
194
+ border-radius: 2px;
195
+ }
196
+
197
+ .ingredients-list {
198
+ list-style: none;
199
+ }
200
+
201
+ .ingredients-list li {
202
+ padding: 10px 0;
203
+ border-bottom: 1px solid #f0f0f0;
204
+ display: flex;
205
+ justify-content: space-between;
206
+ align-items: center;
207
+ }
208
+
209
+ .ingredients-list li:last-child {
210
+ border-bottom: none;
211
+ }
212
+
213
+ .ingredient-name {
214
+ color: #333;
215
+ }
216
+
217
+ .ingredient-quantity {
218
+ color: #667eea;
219
+ font-weight: 600;
220
+ font-size: 0.95rem;
221
+ }
222
+
223
+ .instructions-list {
224
+ list-style: none;
225
+ counter-reset: step;
226
+ }
227
+
228
+ .instructions-list li {
229
+ padding: 12px 0 12px 45px;
230
+ position: relative;
231
+ color: #444;
232
+ line-height: 1.5;
233
+ }
234
+
235
+ .instructions-list li::before {
236
+ counter-increment: step;
237
+ content: counter(step);
238
+ position: absolute;
239
+ left: 0;
240
+ top: 10px;
241
+ width: 28px;
242
+ height: 28px;
243
+ background: #667eea;
244
+ color: white;
245
+ border-radius: 50%;
246
+ display: flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+ font-size: 0.85rem;
250
+ font-weight: 600;
251
+ }
252
+
253
+ /* Bouton générer */
254
+ .generate-section {
255
+ margin-top: 30px;
256
+ text-align: center;
257
+ }
258
+
259
+ .generate-btn {
260
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
261
+ color: white;
262
+ border: none;
263
+ padding: 16px 40px;
264
+ font-size: 1.1rem;
265
+ border-radius: 30px;
266
+ cursor: pointer;
267
+ transition: all 0.3s ease;
268
+ box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
269
+ display: inline-flex;
270
+ align-items: center;
271
+ gap: 10px;
272
+ }
273
+
274
+ .generate-btn:hover {
275
+ transform: translateY(-2px);
276
+ box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
277
+ }
278
+
279
+ .generate-btn:active {
280
+ transform: translateY(0);
281
+ }
282
+
283
+ .generate-btn.loading {
284
+ opacity: 0.7;
285
+ cursor: wait;
286
+ }
287
+
288
+ .generate-btn .spinner {
289
+ display: none;
290
+ width: 20px;
291
+ height: 20px;
292
+ border: 2px solid rgba(255, 255, 255, 0.3);
293
+ border-top-color: white;
294
+ border-radius: 50%;
295
+ animation: spin 0.8s linear infinite;
296
+ }
297
+
298
+ .generate-btn.loading .spinner {
299
+ display: block;
300
+ }
301
+
302
+ .generate-btn.loading .btn-icon {
303
+ display: none;
304
+ }
305
+
306
+ @keyframes spin {
307
+ to { transform: rotate(360deg); }
308
+ }
309
+
310
+ /* Compteur */
311
+ .cocktail-count {
312
+ text-align: center;
313
+ margin-top: 20px;
314
+ color: rgba(255, 255, 255, 0.9);
315
+ font-size: 0.95rem;
316
+ }
317
+
318
+ /* Responsive */
319
+ @media (max-width: 600px) {
320
+ header h1 {
321
+ font-size: 1.8rem;
322
+ }
323
+
324
+ .cocktail-name {
325
+ font-size: 1.5rem;
326
+ }
327
+
328
+ .cocktail-card {
329
+ padding: 20px;
330
+ }
331
+
332
+ .filters {
333
+ justify-content: center;
334
+ }
335
+
336
+ .filter-btn {
337
+ padding: 8px 14px;
338
+ font-size: 0.85rem;
339
+ }
340
+
341
+ .generate-btn {
342
+ padding: 14px 30px;
343
+ font-size: 1rem;
344
+ }
345
+ }
346
+ </style>
347
+ </head>
348
+ <body>
349
+ <div class="container">
350
+ <header>
351
+ <h1>🍹 Générateur de Cocktails</h1>
352
+ <p>Découvrez des recettes de cocktails aléatoires avec leurs ingrédients et instructions</p>
353
+ </header>
354
+
355
+ <!-- Filtres -->
356
+ <div class="filters-container">
357
+ <div class="filters-title">Filtrer par :</div>
358
+ <div class="filters" data-testid="filters">
359
+ <button class="filter-btn active" data-filter="all" data-testid="filter-all">Tous</button>
360
+ <button class="filter-btn" data-filter="alcoholic" data-testid="filter-alcoholic">Avec Alcool</button>
361
+ <button class="filter-btn" data-filter="non-alcoholic" data-testid="filter-non-alcoholic">Sans Alcool</button>
362
+ <button class="filter-btn" data-filter="rum" data-testid="filter-rum">🥃 Rhum</button>
363
+ <button class="filter-btn" data-filter="vodka" data-testid="filter-vodka">🍸 Vodka</button>
364
+ <button class="filter-btn" data-filter="gin" data-testid="filter-gin">🌿 Gin</button>
365
+ <button class="filter-btn" data-filter="tequila" data-testid="filter-tequila">🌵 Tequila</button>
366
+ <button class="filter-btn" data-filter="whiskey" data-testid="filter-whiskey">🥃 Whiskey</button>
367
+ </div>
368
+ </div>
369
+
370
+ <!-- Carte du cocktail -->
371
+ <div class="cocktail-card" data-testid="cocktail-card">
372
+ <div class="cocktail-header">
373
+ <div class="cocktail-title-section">
374
+ <h2 class="cocktail-name" data-testid="cocktail-name">Chargement...</h2>
375
+ <div class="cocktail-meta">
376
+ <span class="cocktail-badge badge-alcoholic" data-testid="cocktail-badge">Avec Alcool</span>
377
+ <span class="cocktail-base" data-testid="cocktail-base">Base : -</span>
378
+ </div>
379
+ </div>
380
+ <div class="glass-section">
381
+ <div class="glass-icon" data-testid="glass-icon">🍹</div>
382
+ <div class="glass-name" data-testid="glass-name">-</div>
383
+ </div>
384
+ </div>
385
+
386
+ <div class="cocktail-content">
387
+ <div class="ingredients-section">
388
+ <h3 class="section-title">Ingrédients</h3>
389
+ <ul class="ingredients-list" data-testid="ingredients-list">
390
+ <!-- Rempli dynamiquement -->
391
+ </ul>
392
+ </div>
393
+
394
+ <div class="instructions-section">
395
+ <h3 class="section-title">Préparation</h3>
396
+ <ol class="instructions-list" data-testid="instructions-list">
397
+ <!-- Rempli dynamiquement -->
398
+ </ol>
399
+ </div>
400
+ </div>
401
+
402
+ <div class="generate-section">
403
+ <button class="generate-btn" data-testid="generate-btn">
404
+ <span class="btn-icon">🎲</span>
405
+ <span class="spinner"></span>
406
+ Nouveau Cocktail
407
+ </button>
408
+ </div>
409
+ </div>
410
+
411
+ <div class="cocktail-count" data-testid="cocktail-count">25 cocktails disponibles</div>
412
+ </div>
413
+
414
+ <script src="cocktails.js"></script>
415
+ <script>
416
+ /**
417
+ * Générateur de Cocktails Aléatoires
418
+ * Interface interactive pour le dossier fake-features
419
+ */
420
+ class CocktailGenerator {
421
+ constructor() {
422
+ this.cocktails = COCKTAILS_DATABASE;
423
+ this.currentFilter = 'all';
424
+ this.currentCocktail = null;
425
+ this.lastCocktailId = null;
426
+ this.isLoading = false;
427
+
428
+ // Mapping des types de verres vers des icônes
429
+ this.glassIcons = {
430
+ 'Highball': '🥃',
431
+ 'Hurricane': '🍹',
432
+ 'Coupette': '🍸',
433
+ 'Old Fashioned': '🥃',
434
+ 'Martini': '🍸',
435
+ 'Mug en cuivre': '🍺',
436
+ 'Tumbler': '🥃',
437
+ 'Verre à Irish Coffee': '☕',
438
+ 'Grand verre': '🥛'
439
+ };
440
+
441
+ this.init();
442
+ }
443
+
444
+ init() {
445
+ this.bindEvents();
446
+ this.generateRandomCocktail();
447
+ }
448
+
449
+ bindEvents() {
450
+ // Bouton générer
451
+ document.querySelector('[data-testid="generate-btn"]').addEventListener('click', () => {
452
+ this.generateRandomCocktail();
453
+ });
454
+
455
+ // Filtres
456
+ document.querySelectorAll('.filter-btn').forEach(btn => {
457
+ btn.addEventListener('click', (e) => {
458
+ this.setFilter(e.target.dataset.filter);
459
+ });
460
+ });
461
+ }
462
+
463
+ setFilter(filter) {
464
+ this.currentFilter = filter;
465
+
466
+ // Mettre à jour l'UI des filtres
467
+ document.querySelectorAll('.filter-btn').forEach(btn => {
468
+ btn.classList.toggle('active', btn.dataset.filter === filter);
469
+ });
470
+
471
+ // Réinitialiser lastCocktailId pour permettre la sélection de n'importe quel cocktail
472
+ this.lastCocktailId = null;
473
+
474
+ // Mettre à jour le compteur
475
+ this.updateCocktailCount();
476
+
477
+ // Générer un nouveau cocktail avec le filtre
478
+ this.generateRandomCocktail();
479
+ }
480
+
481
+ getFilteredCocktails() {
482
+ if (this.currentFilter === 'all') {
483
+ return this.cocktails;
484
+ }
485
+
486
+ if (this.currentFilter === 'alcoholic') {
487
+ return this.cocktails.filter(c => c.category === 'alcoholic');
488
+ }
489
+
490
+ if (this.currentFilter === 'non-alcoholic') {
491
+ return this.cocktails.filter(c => c.category === 'non-alcoholic');
492
+ }
493
+
494
+ return this.cocktails.filter(c => c.base === this.currentFilter);
495
+ }
496
+
497
+ generateRandomCocktail() {
498
+ if (this.isLoading) return;
499
+
500
+ const btn = document.querySelector('[data-testid="generate-btn"]');
501
+ const card = document.querySelector('[data-testid="cocktail-card"]');
502
+
503
+ // Animation de chargement
504
+ this.isLoading = true;
505
+ btn.classList.add('loading');
506
+ card.classList.add('loading');
507
+
508
+ setTimeout(() => {
509
+ const filtered = this.getFilteredCocktails();
510
+
511
+ if (filtered.length === 0) {
512
+ this.showNoCocktails();
513
+ this.isLoading = false;
514
+ btn.classList.remove('loading');
515
+ card.classList.remove('loading');
516
+ return;
517
+ }
518
+
519
+ // Éviter de répéter le même cocktail
520
+ let availableCocktails = filtered;
521
+ if (filtered.length > 1 && this.lastCocktailId !== null) {
522
+ availableCocktails = filtered.filter(c => c.id !== this.lastCocktailId);
523
+ }
524
+
525
+ const randomIndex = Math.floor(Math.random() * availableCocktails.length);
526
+ const cocktail = availableCocktails[randomIndex];
527
+
528
+ this.lastCocktailId = cocktail.id;
529
+ this.currentCocktail = cocktail;
530
+
531
+ this.displayCocktail(cocktail);
532
+ this.updateCocktailCount();
533
+
534
+ this.isLoading = false;
535
+ btn.classList.remove('loading');
536
+ card.classList.remove('loading');
537
+ }, 500);
538
+ }
539
+
540
+ displayCocktail(cocktail) {
541
+ // Nom
542
+ document.querySelector('[data-testid="cocktail-name"]').textContent = cocktail.name;
543
+
544
+ // Badge catégorie
545
+ const badge = document.querySelector('[data-testid="cocktail-badge"]');
546
+ if (cocktail.category === 'alcoholic') {
547
+ badge.textContent = 'Avec Alcool';
548
+ badge.className = 'cocktail-badge badge-alcoholic';
549
+ } else {
550
+ badge.textContent = 'Sans Alcool';
551
+ badge.className = 'cocktail-badge badge-non-alcoholic';
552
+ }
553
+
554
+ // Base
555
+ const baseText = this.formatBase(cocktail.base);
556
+ document.querySelector('[data-testid="cocktail-base"]').textContent = `Base : ${baseText}`;
557
+
558
+ // Verre avec icône
559
+ const glassIcon = this.glassIcons[cocktail.glass] || '🥃';
560
+ document.querySelector('[data-testid="glass-icon"]').textContent = glassIcon;
561
+ document.querySelector('[data-testid="glass-name"]').textContent = cocktail.glass;
562
+
563
+ // Ingrédients
564
+ const ingredientsList = document.querySelector('[data-testid="ingredients-list"]');
565
+ ingredientsList.innerHTML = cocktail.ingredients.map(ing => `
566
+ <li>
567
+ <span class="ingredient-name">${ing.name}</span>
568
+ <span class="ingredient-quantity">${ing.quantity}</span>
569
+ </li>
570
+ `).join('');
571
+
572
+ // Instructions
573
+ const instructionsList = document.querySelector('[data-testid="instructions-list"]');
574
+ instructionsList.innerHTML = cocktail.instructions.map(instr => `
575
+ <li>${instr}</li>
576
+ `).join('');
577
+ }
578
+
579
+ showNoCocktails() {
580
+ document.querySelector('[data-testid="cocktail-name"]').textContent = 'Aucun cocktail trouvé';
581
+ document.querySelector('[data-testid="cocktail-badge"]').textContent = '-';
582
+ document.querySelector('[data-testid="cocktail-base"]').textContent = 'Base : -';
583
+ document.querySelector('[data-testid="glass-icon"]').textContent = '🤷';
584
+ document.querySelector('[data-testid="glass-name"]').textContent = '-';
585
+ document.querySelector('[data-testid="ingredients-list"]').innerHTML = '<li>Aucun ingrédient</li>';
586
+ document.querySelector('[data-testid="instructions-list"]').innerHTML = '<li>Essayez un autre filtre</li>';
587
+ }
588
+
589
+ formatBase(base) {
590
+ const baseNames = {
591
+ 'rum': 'Rhum',
592
+ 'vodka': 'Vodka',
593
+ 'gin': 'Gin',
594
+ 'tequila': 'Tequila',
595
+ 'whiskey': 'Whiskey',
596
+ 'sans alcool': 'Sans Alcool'
597
+ };
598
+ return baseNames[base] || base;
599
+ }
600
+
601
+ updateCocktailCount() {
602
+ const filtered = this.getFilteredCocktails();
603
+ const total = this.cocktails.length;
604
+ const countEl = document.querySelector('[data-testid="cocktail-count"]');
605
+
606
+ if (this.currentFilter === 'all') {
607
+ countEl.textContent = `${total} cocktails disponibles`;
608
+ } else {
609
+ countEl.textContent = `${filtered.length} cocktails sur ${total}`;
610
+ }
611
+ }
612
+ }
613
+
614
+ // Initialiser l'application
615
+ document.addEventListener('DOMContentLoaded', () => {
616
+ new CocktailGenerator();
617
+ });
618
+ </script>
619
+ </body>
620
+ </html>