web: the QR card hands out the look that made the photo

A photo's landing section can now be the QR card, and that section is the
only one that hands something out: the server writes the photo's own stored
look back as the app's .recipe file, at
GET /api/photos/:id/preset.recipe, for any row the curator ticked into the
qr slot. Nothing new is stored — the file is built from the recipe the
upload already carried, so it works for a photo uploaded by the phone too.

The admin pane grows a fourth checkbox and a fourth row (QR card); the
row draws the download link as a scannable code, and the box is dead for a
photo with no stored look. The landing's QR card now encodes the curated
photo's own link instead of a mock address. The listing exposes
hasPreset, never the recipe itself.
This commit is contained in:
2026-09-18 16:57:46 +07:00
parent a35ecf4f1c
commit 8a889db069
11 changed files with 233 additions and 18 deletions
+3 -1
View File
@@ -172,8 +172,10 @@ export const vi = {
'adm.pickStrip': 'Dải phim',
'adm.pickTester': 'Live preset tester',
'adm.pickCreator': 'Custom recipe creator',
'adm.pickQr': 'Thẻ QR',
'adm.noPreset': 'không có look để chia sẻ',
'adm.rowEmpty': 'Chưa có gì ở đây.',
'adm.slotHint': 'Tích vào những mục ảnh sẽ xuất hiện — một ảnh có thể nằm cùng lúc ở nhiều mục, và mỗi mục bốc ngẫu nhiên một ảnh trong nhóm của nó mỗi lần ghé. Bỏ tích hết sẽ gỡ ảnh khỏi landing mà không xoá — chủ ảnh vẫn giữ nó trong MY PHOTOS.',
'adm.slotHint': 'Tích vào những mục ảnh sẽ xuất hiện — một ảnh có thể nằm cùng lúc ở nhiều mục, và mỗi mục bốc ngẫu nhiên một ảnh trong nhóm của nó mỗi lần ghé. Bỏ tích hết sẽ gỡ ảnh khỏi landing mà không xoá — chủ ảnh vẫn giữ nó trong MY PHOTOS. Mục QR là mục duy nhất phát công thức: thẻ của nó vẽ một mã tải chính tệp .recipe của ảnh để app trên điện thoại quét vào.',
'adm.signIn': 'Đăng nhập bằng tài khoản quản trị',
'adm.notAdmin': 'Tài khoản này không có quyền quản trị.',
'adm.empty': 'Chưa có ảnh đóng góp nào.',