winebox 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

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.
@@ -982,6 +982,41 @@ h3 {
982
982
  text-align: left;
983
983
  }
984
984
 
985
+ /* Password Toggle */
986
+ .password-input-wrapper {
987
+ position: relative;
988
+ display: flex;
989
+ align-items: center;
990
+ }
991
+
992
+ .password-input-wrapper input {
993
+ flex: 1;
994
+ padding-right: 3rem;
995
+ }
996
+
997
+ .password-toggle {
998
+ position: absolute;
999
+ right: 0.75rem;
1000
+ background: none;
1001
+ border: none;
1002
+ cursor: pointer;
1003
+ padding: 0.5rem;
1004
+ color: var(--text-muted);
1005
+ transition: color 0.2s;
1006
+ display: flex;
1007
+ align-items: center;
1008
+ justify-content: center;
1009
+ }
1010
+
1011
+ .password-toggle:hover {
1012
+ color: var(--primary-color);
1013
+ }
1014
+
1015
+ .password-toggle svg {
1016
+ width: 20px;
1017
+ height: 20px;
1018
+ }
1019
+
985
1020
  .login-error {
986
1021
  background: rgba(166, 61, 64, 0.1);
987
1022
  color: var(--error-color);
@@ -1084,3 +1119,312 @@ body.logged-out #user-info {
1084
1119
  content: '...';
1085
1120
  }
1086
1121
  }
1122
+
1123
+ /* Checkin Confirmation Modal */
1124
+ .checkin-confirm {
1125
+ text-align: center;
1126
+ }
1127
+
1128
+ .checkin-confirm-header {
1129
+ margin-bottom: 1.5rem;
1130
+ }
1131
+
1132
+ .checkin-confirm-icon {
1133
+ width: 60px;
1134
+ height: 60px;
1135
+ background: var(--success-color);
1136
+ color: white;
1137
+ border-radius: 50%;
1138
+ display: inline-flex;
1139
+ align-items: center;
1140
+ justify-content: center;
1141
+ font-size: 2rem;
1142
+ margin-bottom: 1rem;
1143
+ }
1144
+
1145
+ .checkin-confirm-header h3 {
1146
+ color: var(--success-color);
1147
+ margin: 0;
1148
+ }
1149
+
1150
+ .checkin-confirm-content {
1151
+ display: grid;
1152
+ grid-template-columns: auto 1fr;
1153
+ gap: 1.5rem;
1154
+ text-align: left;
1155
+ margin-bottom: 1.5rem;
1156
+ }
1157
+
1158
+ .checkin-confirm-image {
1159
+ width: 150px;
1160
+ height: 200px;
1161
+ border-radius: var(--radius);
1162
+ overflow: hidden;
1163
+ background: var(--background-color);
1164
+ border: 1px solid var(--border-color);
1165
+ }
1166
+
1167
+ .checkin-confirm-image img {
1168
+ width: 100%;
1169
+ height: 100%;
1170
+ object-fit: cover;
1171
+ }
1172
+
1173
+ .checkin-confirm-details h4 {
1174
+ color: var(--primary-color);
1175
+ margin-bottom: 1rem;
1176
+ font-size: 1.25rem;
1177
+ }
1178
+
1179
+ .checkin-confirm-fields {
1180
+ display: grid;
1181
+ grid-template-columns: repeat(2, 1fr);
1182
+ gap: 0.75rem;
1183
+ }
1184
+
1185
+ .checkin-confirm-field {
1186
+ background: var(--background-color);
1187
+ padding: 0.5rem 0.75rem;
1188
+ border-radius: var(--radius);
1189
+ }
1190
+
1191
+ .checkin-confirm-field .label {
1192
+ font-size: 0.75rem;
1193
+ color: var(--text-muted);
1194
+ text-transform: uppercase;
1195
+ letter-spacing: 0.5px;
1196
+ }
1197
+
1198
+ .checkin-confirm-field .value {
1199
+ font-weight: 500;
1200
+ color: var(--text-color);
1201
+ }
1202
+
1203
+ .checkin-confirm-field .value.empty {
1204
+ color: var(--text-muted);
1205
+ font-style: italic;
1206
+ font-weight: normal;
1207
+ }
1208
+
1209
+ .checkin-confirm-ocr {
1210
+ text-align: left;
1211
+ margin-bottom: 1.5rem;
1212
+ }
1213
+
1214
+ .checkin-confirm-ocr h5 {
1215
+ color: var(--text-color);
1216
+ margin-bottom: 0.75rem;
1217
+ font-size: 0.9rem;
1218
+ }
1219
+
1220
+ .ocr-text-container {
1221
+ background: var(--background-color);
1222
+ border-radius: var(--radius);
1223
+ padding: 1rem;
1224
+ max-height: 200px;
1225
+ overflow-y: auto;
1226
+ }
1227
+
1228
+ .ocr-section {
1229
+ margin-bottom: 1rem;
1230
+ }
1231
+
1232
+ .ocr-section:last-child {
1233
+ margin-bottom: 0;
1234
+ }
1235
+
1236
+ .ocr-section strong {
1237
+ display: block;
1238
+ font-size: 0.8rem;
1239
+ color: var(--text-muted);
1240
+ margin-bottom: 0.25rem;
1241
+ }
1242
+
1243
+ .ocr-section pre {
1244
+ font-family: inherit;
1245
+ font-size: 0.85rem;
1246
+ white-space: pre-wrap;
1247
+ word-break: break-word;
1248
+ margin: 0;
1249
+ color: var(--text-color);
1250
+ }
1251
+
1252
+ .checkin-confirm .form-actions {
1253
+ justify-content: center;
1254
+ }
1255
+
1256
+ @media (max-width: 600px) {
1257
+ .checkin-confirm-content {
1258
+ grid-template-columns: 1fr;
1259
+ }
1260
+
1261
+ .checkin-confirm-image {
1262
+ width: 100%;
1263
+ height: 150px;
1264
+ }
1265
+
1266
+ .checkin-confirm-fields {
1267
+ grid-template-columns: 1fr;
1268
+ }
1269
+ }
1270
+
1271
+ /* Collapsible Sections */
1272
+ .collapsible {
1273
+ margin-bottom: 1.5rem;
1274
+ }
1275
+
1276
+ .collapsible-header {
1277
+ display: flex;
1278
+ justify-content: space-between;
1279
+ align-items: center;
1280
+ cursor: pointer;
1281
+ padding: 0.5rem 0;
1282
+ user-select: none;
1283
+ }
1284
+
1285
+ .collapsible-header h3 {
1286
+ margin: 0;
1287
+ color: var(--text-muted);
1288
+ font-size: 1rem;
1289
+ display: flex;
1290
+ align-items: center;
1291
+ gap: 0.5rem;
1292
+ }
1293
+
1294
+ .scan-method-badge {
1295
+ font-size: 0.7rem;
1296
+ font-weight: 600;
1297
+ padding: 0.2rem 0.5rem;
1298
+ border-radius: 999px;
1299
+ background: var(--primary-color);
1300
+ color: white;
1301
+ text-transform: uppercase;
1302
+ letter-spacing: 0.5px;
1303
+ }
1304
+
1305
+ .collapsible-header:hover h3 {
1306
+ color: var(--primary-color);
1307
+ }
1308
+
1309
+ .collapse-icon {
1310
+ font-size: 1.25rem;
1311
+ font-weight: bold;
1312
+ color: var(--text-muted);
1313
+ transition: transform 0.2s;
1314
+ }
1315
+
1316
+ .collapsible.open .collapse-icon {
1317
+ transform: rotate(45deg);
1318
+ }
1319
+
1320
+ .collapsible-content {
1321
+ padding-top: 1rem;
1322
+ }
1323
+
1324
+ /* Raw OCR Text Display */
1325
+ .ocr-raw-text {
1326
+ background: var(--background-color);
1327
+ border-radius: var(--radius);
1328
+ padding: 1rem;
1329
+ }
1330
+
1331
+ .ocr-raw-section {
1332
+ margin-bottom: 1rem;
1333
+ }
1334
+
1335
+ .ocr-raw-section:last-child {
1336
+ margin-bottom: 0;
1337
+ }
1338
+
1339
+ .ocr-raw-section label {
1340
+ display: block;
1341
+ font-size: 0.85rem;
1342
+ font-weight: 500;
1343
+ color: var(--text-muted);
1344
+ margin-bottom: 0.5rem;
1345
+ }
1346
+
1347
+ .ocr-raw-section pre {
1348
+ background: var(--card-background);
1349
+ border: 1px solid var(--border-color);
1350
+ border-radius: var(--radius);
1351
+ padding: 0.75rem;
1352
+ font-family: monospace;
1353
+ font-size: 0.8rem;
1354
+ white-space: pre-wrap;
1355
+ word-break: break-word;
1356
+ max-height: 150px;
1357
+ overflow-y: auto;
1358
+ margin: 0;
1359
+ }
1360
+
1361
+ /* Wine Detail Label Text */
1362
+ .wine-detail-label-text {
1363
+ margin-top: 1rem;
1364
+ padding-top: 1rem;
1365
+ border-top: 1px solid var(--border-color);
1366
+ }
1367
+
1368
+ .wine-detail-label-text .collapsible-header {
1369
+ padding: 0;
1370
+ }
1371
+
1372
+ .wine-detail-label-text .collapsible-header .label {
1373
+ font-size: 0.85rem;
1374
+ color: var(--primary-color);
1375
+ cursor: pointer;
1376
+ }
1377
+
1378
+ .wine-detail-label-text .collapsible-header .label:hover {
1379
+ text-decoration: underline;
1380
+ }
1381
+
1382
+ /* Auto-fill Animation */
1383
+ .auto-filled {
1384
+ animation: autoFillPulse 0.5s ease;
1385
+ background-color: rgba(74, 124, 89, 0.1) !important;
1386
+ }
1387
+
1388
+ @keyframes autoFillPulse {
1389
+ 0% {
1390
+ background-color: rgba(74, 124, 89, 0.3);
1391
+ }
1392
+ 100% {
1393
+ background-color: rgba(74, 124, 89, 0.1);
1394
+ }
1395
+ }
1396
+
1397
+ /* Scanning Indicator */
1398
+ .form-note.scanning {
1399
+ color: var(--primary-color);
1400
+ font-weight: 500;
1401
+ }
1402
+
1403
+ .form-note.scanning::after {
1404
+ content: '';
1405
+ animation: dots 1.5s steps(4, end) infinite;
1406
+ }
1407
+
1408
+ /* Footer */
1409
+ #app-footer {
1410
+ background: var(--primary-dark);
1411
+ color: rgba(255, 255, 255, 0.7);
1412
+ text-align: center;
1413
+ padding: 1rem 2rem;
1414
+ font-size: 0.85rem;
1415
+ margin-top: 2rem;
1416
+ }
1417
+
1418
+ #app-footer #app-info {
1419
+ display: flex;
1420
+ justify-content: center;
1421
+ align-items: center;
1422
+ gap: 0.5rem;
1423
+ }
1424
+
1425
+ #app-footer .version {
1426
+ background: rgba(255, 255, 255, 0.15);
1427
+ padding: 0.15rem 0.5rem;
1428
+ border-radius: 4px;
1429
+ font-size: 0.75rem;
1430
+ }
@@ -0,0 +1,22 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2
+ <defs>
3
+ <linearGradient id="bottle" x1="0%" y1="0%" x2="100%" y2="100%">
4
+ <stop offset="0%" style="stop-color:#8b4049"/>
5
+ <stop offset="100%" style="stop-color:#5a252c"/>
6
+ </linearGradient>
7
+ <linearGradient id="wine" x1="0%" y1="0%" x2="0%" y2="100%">
8
+ <stop offset="0%" style="stop-color:#722f37"/>
9
+ <stop offset="100%" style="stop-color:#4a1f24"/>
10
+ </linearGradient>
11
+ </defs>
12
+ <!-- Bottle neck -->
13
+ <rect x="26" y="4" width="12" height="14" rx="2" fill="url(#bottle)"/>
14
+ <!-- Bottle neck ring -->
15
+ <rect x="24" y="16" width="16" height="4" rx="1" fill="url(#bottle)"/>
16
+ <!-- Bottle body -->
17
+ <path d="M24 20 L24 24 Q18 28 18 36 L18 56 Q18 60 22 60 L42 60 Q46 60 46 56 L46 36 Q46 28 40 24 L40 20 Z" fill="url(#bottle)"/>
18
+ <!-- Wine level -->
19
+ <path d="M20 40 L20 56 Q20 58 22 58 L42 58 Q44 58 44 56 L44 40 Q44 38 32 42 Q20 38 20 40 Z" fill="url(#wine)"/>
20
+ <!-- Highlight -->
21
+ <ellipse cx="38" cy="48" rx="2" ry="6" fill="rgba(255,255,255,0.15)"/>
22
+ </svg>
winebox/static/index.html CHANGED
@@ -7,6 +7,7 @@
7
7
  <meta name="mobile-web-app-capable" content="yes">
8
8
  <meta name="theme-color" content="#722f37">
9
9
  <title>WineBox - Wine Cellar Management</title>
10
+ <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
10
11
  <link rel="stylesheet" href="/static/css/style.css">
11
12
  </head>
12
13
  <body>
@@ -40,7 +41,19 @@
40
41
  </div>
41
42
  <div class="form-group">
42
43
  <label for="login-password">Password</label>
43
- <input type="password" id="login-password" name="password" required autocomplete="current-password">
44
+ <div class="password-input-wrapper">
45
+ <input type="password" id="login-password" name="password" required autocomplete="current-password">
46
+ <button type="button" class="password-toggle" aria-label="Show password">
47
+ <svg class="eye-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
48
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
49
+ <circle cx="12" cy="12" r="3"></circle>
50
+ </svg>
51
+ <svg class="eye-off-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="display: none;">
52
+ <path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path>
53
+ <line x1="1" y1="1" x2="23" y2="23"></line>
54
+ </svg>
55
+ </button>
56
+ </div>
44
57
  </div>
45
58
  <div id="login-error" class="login-error" style="display: none;"></div>
46
59
  <button type="submit" class="btn btn-primary btn-full">Sign In</button>
@@ -152,6 +165,25 @@
152
165
  </div>
153
166
  </div>
154
167
 
168
+ <div class="form-section collapsible" id="label-text-section" style="display: none;">
169
+ <div class="collapsible-header" id="label-text-toggle">
170
+ <h3>Raw Label Text</h3>
171
+ <span class="collapse-icon">+</span>
172
+ </div>
173
+ <div class="collapsible-content" id="label-text-content" style="display: none;">
174
+ <div class="ocr-raw-text">
175
+ <div class="ocr-raw-section">
176
+ <label>Front Label OCR:</label>
177
+ <pre id="raw-front-label-text"></pre>
178
+ </div>
179
+ <div class="ocr-raw-section" id="raw-back-label-section" style="display: none;">
180
+ <label>Back Label OCR:</label>
181
+ <pre id="raw-back-label-text"></pre>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
155
187
  <div class="form-actions">
156
188
  <button type="submit" class="btn btn-primary">Check In Wine</button>
157
189
  <button type="reset" class="btn btn-secondary">Clear Form</button>
@@ -263,6 +295,48 @@
263
295
  </div>
264
296
  </div>
265
297
 
298
+ <!-- Checkin Confirmation Modal -->
299
+ <div id="checkin-confirm-modal" class="modal">
300
+ <div class="modal-content">
301
+ <span class="modal-close">&times;</span>
302
+ <div class="checkin-confirm">
303
+ <div class="checkin-confirm-header">
304
+ <div class="checkin-confirm-icon">&#10003;</div>
305
+ <h3>Wine Checked In Successfully</h3>
306
+ </div>
307
+ <div class="checkin-confirm-content">
308
+ <div class="checkin-confirm-image" id="checkin-confirm-image"></div>
309
+ <div class="checkin-confirm-details">
310
+ <h4 id="checkin-confirm-name"></h4>
311
+ <div class="checkin-confirm-fields" id="checkin-confirm-fields"></div>
312
+ </div>
313
+ </div>
314
+ <div class="checkin-confirm-ocr">
315
+ <h5>Extracted Label Text</h5>
316
+ <div class="ocr-text-container">
317
+ <div class="ocr-section">
318
+ <strong>Front Label:</strong>
319
+ <pre id="checkin-confirm-front-ocr"></pre>
320
+ </div>
321
+ <div class="ocr-section" id="checkin-confirm-back-ocr-section" style="display: none;">
322
+ <strong>Back Label:</strong>
323
+ <pre id="checkin-confirm-back-ocr"></pre>
324
+ </div>
325
+ </div>
326
+ </div>
327
+ <div class="form-actions">
328
+ <button type="button" class="btn btn-primary" id="checkin-confirm-done">Done</button>
329
+ <button type="button" class="btn btn-secondary" id="checkin-confirm-another">Check In Another</button>
330
+ </div>
331
+ </div>
332
+ </div>
333
+ </div>
334
+
335
+ <!-- Footer -->
336
+ <footer id="app-footer">
337
+ <span id="app-info">WineBox</span>
338
+ </footer>
339
+
266
340
  <!-- Toast Notifications -->
267
341
  <div id="toast-container"></div>
268
342