0489028486
CI / test (push) Has been cancelled
v2 tokens were duplicated: in design-v2.scss for the SPA, inlined in login.html.twig for Twig. Two places to keep in sync. Now: one shared /public/css/wevisto-design.css loaded by every Twig standalone template AND linked from the SPA index.html. It contains: - Brand constants (yellow / navy / fonts) - v2 tokens with per-theme dusk overrides - v2 base body bg + editorial typography defaults - v2 overrides for the .card / .btn / .field-error / .logo-badge patterns used across all Twig templates The SPA's design-v2.scss now holds only SPA-specific composition: side rail at desktop, frame card, theme swatch harbor preview, settings polish. No token duplication. Result: changing a v2 color in one file flows to every surface in both worlds. Adding v2 to another Twig template only requires the existing shared CSS link (already wired up to all 11 standalone templates). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 line
16 KiB
JavaScript
1 line
16 KiB
JavaScript
import{A as e,B as t,C as n,F as r,K as i,N as a,S as o,U as s,V as c,Y as l,_ as u,d,f,g as p,h as m,p as h,q as g,t as _,u as v,v as y,x as b,y as x,z as S}from"./_plugin-vue_export-helper-BNDVmFr7.js";import{a as C,i as ee,o as te,s as w}from"./index-mIDwNQXq.js";import{i as T,n as E,r as ne,t as D}from"./BaseBottomSheet-Bsol3Sat.js";import{t as re}from"./PullToRefresh-CSjUpm5h.js";import{t as O}from"./DevicePicker-BnLOaG74.js";var k={class:`approve-card`},A=[`src`,`alt`],j={class:`approve-card__body`},ie={class:`approve-card__from`},M={class:`approve-card__date`},N={key:0,class:`approve-card__status`},P={class:`approve-card__actions`},ae=_(n({__name:`ApproveCard`,props:{item:{}},emits:[`updated`],setup(e,{emit:n}){let r=e,c=n,d=C(),f=T(),_=s(!1),v=s(!1),S=s([]),ee=m(()=>new Date(r.item.sharedAt).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`}));async function te(){_.value=!1,v.value=!0;try{c(`updated`,await d.approveShared(r.item.id,S.value))}finally{v.value=!1,S.value=[]}}async function w(){v.value=!0;try{c(`updated`,await d.declineShared(r.item.id))}finally{v.value=!1}}return(n,r)=>(a(),x(h,null,[p(`div`,k,[p(`img`,{src:e.item.thumbnailUrl,alt:`Photo from ${e.item.sharedBy}`,class:`approve-card__thumb`,loading:`lazy`},null,8,A),p(`div`,j,[p(`p`,ie,[r[3]||=b(`From `,-1),p(`strong`,null,l(e.item.sharedBy),1)]),p(`p`,M,l(ee.value),1),e.item.status===`pending`?y(``,!0):(a(),x(`div`,N,[p(`span`,{class:g([`approve-card__badge`,`approve-card__badge--${e.item.status}`])},l(e.item.status),3)])),p(`div`,P,[e.item.status===`pending`||e.item.status===`declined`?(a(),u(E,{key:0,variant:`primary`,size:`sm`,disabled:v.value,onClick:r[0]||=e=>_.value=!0},{default:t(()=>[b(l(e.item.status===`declined`?`Add anyway`:`Add to frame`),1)]),_:1},8,[`disabled`])):y(``,!0),e.item.status===`pending`||e.item.status===`approved`?(a(),u(E,{key:1,variant:`ghost`,size:`sm`,disabled:v.value,onClick:w},{default:t(()=>[b(l(e.item.status===`approved`?`Remove`:`Decline`),1)]),_:1},8,[`disabled`])):y(``,!0)])])]),o(O,{modelValue:_.value,"onUpdate:modelValue":r[1]||=e=>_.value=e,devices:i(f).devices,selected:S.value,uploading:v.value,"confirm-label":`Add to frames`,"onUpdate:selected":r[2]||=e=>S.value=e,onConfirm:te},null,8,[`modelValue`,`devices`,`selected`,`uploading`])],64))}}),[[`__scopeId`,`data-v-6d3dd8b4`]]),F={key:0,class:`manage__empty`},I={key:1,class:`manage__list`},L={class:`manage__device`},oe={class:`manage__device-name`},R={class:`manage__device-meta`},se=[`disabled`,`aria-label`,`onClick`],z={width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},ce={key:0,d:`M7 11V7a5 5 0 0 1 10 0v4`},le={key:1,d:`M7 11V7a5 5 0 0 1 9.9-1`},ue={key:0},de={class:`manage__toggle-wrap`},B={class:`manage__toggle-label`},V=[`disabled`,`aria-label`,`onClick`],fe=_(n({__name:`ManageImageSheet`,props:{modelValue:{type:Boolean},image:{},devices:{}},emits:[`update:modelValue`,`approval`,`lock`],setup(e,{emit:n}){let i=e,c=n,d=s(null),f=s(null);function m(e){return!!i.image?.approvedDeviceIds.includes(e)}function _(e){if(!i.image)return;d.value=e.id;let t=!m(e.id);c(`approval`,{imageId:i.image.id,deviceId:e.id,approved:t}),setTimeout(()=>{d.value=null},200)}function v(e){if(!i.image||!m(e.id))return;f.value=e.id;let t=e.lockedImageId!==i.image.id;c(`lock`,{imageId:i.image.id,deviceId:e.id,locked:t}),setTimeout(()=>{f.value=null},200)}return(n,i)=>(a(),u(D,{"model-value":e.modelValue,label:`Manage frames for this photo`,"onUpdate:modelValue":i[1]||=e=>n.$emit(`update:modelValue`,e)},{default:t(()=>[i[4]||=p(`h2`,{class:`manage__title`},`Manage frames`,-1),i[5]||=p(`p`,{class:`manage__sub`},` Toggle which frames show this photo, or lock it to a frame so it stays visible until you unlock it. `,-1),e.devices.length?(a(),x(`div`,I,[(a(!0),x(h,null,r(e.devices,t=>(a(),x(`div`,{key:t.id,class:`manage__row`},[p(`div`,L,[p(`span`,oe,l(t.name),1),p(`span`,R,l(t.orientation),1)]),m(t.id)?(a(),x(`button`,{key:0,type:`button`,class:g([`manage__lock`,{"manage__lock--on":t.lockedImageId===e.image?.id}]),disabled:f.value===t.id,"aria-label":t.lockedImageId===e.image?.id?`Unlock from ${t.name}`:`Lock to ${t.name}`,onClick:e=>v(t)},[(a(),x(`svg`,z,[i[2]||=p(`rect`,{x:`3`,y:`11`,width:`18`,height:`11`,rx:`2`,ry:`2`},null,-1),t.lockedImageId===e.image?.id?(a(),x(`path`,ce)):(a(),x(`path`,le))])),t.lockedImageId===e.image?.id?(a(),x(`span`,ue,`Locked`)):y(``,!0)],10,se)):y(``,!0),p(`label`,de,[p(`span`,B,l(m(t.id)?`Show`:`Hidden`),1),p(`button`,{type:`button`,class:g([`manage__toggle`,{"manage__toggle--on":m(t.id)}]),disabled:d.value===t.id,"aria-label":m(t.id)?`Hide this photo from ${t.name}`:`Show this photo on ${t.name}`,onClick:e=>_(t)},null,10,V)])]))),128))])):(a(),x(`div`,F,` You don't have any frames set up yet. `)),o(E,{variant:`primary`,class:`manage__done`,onClick:i[0]||=e=>n.$emit(`update:modelValue`,!1)},{default:t(()=>[...i[3]||=[b(` Done `,-1)]]),_:1})]),_:1},8,[`model-value`]))}}),[[`__scopeId`,`data-v-8355addd`]]),H={class:`share-sheet__field`},U=[`onKeydown`],W={key:0,class:`share-sheet__error`},G={key:1,class:`share-sheet__success`},pe=_(n({__name:`ShareSheet`,props:{modelValue:{type:Boolean},imageId:{}},emits:[`update:modelValue`],setup(e,{emit:n}){let r=e,i=C(),m=s(``),h=s(!1),g=s(``),_=s(``);async function S(){if(g.value=``,_.value=``,m.value.trim()){h.value=!0;try{await i.shareImage(r.imageId,m.value.trim()),_.value=`Invite sent to ${m.value.trim()}`,m.value=``}catch(e){g.value=e instanceof Error?e.message:`Failed to send`}finally{h.value=!1}}}return(n,r)=>(a(),u(D,{"model-value":e.modelValue,label:`Share photo`,"onUpdate:modelValue":r[1]||=e=>n.$emit(`update:modelValue`,e)},{default:t(()=>[r[2]||=p(`h2`,{class:`share-sheet__title`},`Share with someone`,-1),r[3]||=p(`p`,{class:`share-sheet__sub`},`They'll get an email and can add it to their frame.`,-1),p(`div`,H,[c(p(`input`,{"onUpdate:modelValue":r[0]||=e=>m.value=e,type:`email`,class:`share-sheet__input`,placeholder:`their@email.com`,autocomplete:`email`,onKeydown:d(f(S,[`prevent`]),[`enter`])},null,40,U),[[v,m.value]])]),g.value?(a(),x(`p`,W,l(g.value),1)):y(``,!0),_.value?(a(),x(`p`,G,l(_.value),1)):y(``,!0),o(E,{variant:`primary`,class:`share-sheet__btn`,disabled:h.value||!m.value.trim(),onClick:S},{default:t(()=>[b(l(h.value?`Sending…`:`Send invite`),1)]),_:1},8,[`disabled`])]),_:1},8,[`model-value`]))}}),[[`__scopeId`,`data-v-24296e7b`]]),me={class:`library`},he={class:`library__header`},ge={class:`library__tabs`,role:`tablist`},_e=[`aria-selected`,`onClick`],ve={key:0,class:`library__loading`},ye={key:0,class:`library__empty`},be={key:1,class:`library__grid`},xe={class:`library__thumb`},Se=[`src`,`alt`],Ce=[`title`],we={class:`library__thumb-actions`},Te=[`aria-label`,`title`,`onClick`],Ee=[`aria-label`,`disabled`,`onClick`],De={key:0,width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},Oe={key:1,width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2`,"aria-hidden":`true`},ke=[`aria-label`,`onClick`],Ae=[`onClick`],je=[`aria-label`,`onClick`],Me={class:`library__manage-summary`},Ne={key:0,class:`library__manage-lock`},Pe={class:`library__subtabs`,role:`tablist`},Fe=[`aria-selected`,`onClick`],Ie={key:0,class:`library__loading`},Le={key:1,class:`library__shared-empty`},Re={class:`library__empty-title`},ze={class:`library__empty-sub`},Be={key:2,class:`library__shared-list`},Ve={key:3,class:`library__pagination`},He=[`disabled`],Ue={class:`library__page-info`},We=[`disabled`],Ge={class:`library__sheet-actions`},K=_(n({__name:`LibraryView`,setup(n){let c=w(),d=C(),f=T(),_=ne(),v=ee(),O=te(),k=[{id:`all`,label:`All`},{id:`mine`,label:`Mine`},{id:`shared`,label:`Shared`}];function A(e){return k.some(t=>t.id===e)?e:`all`}let j=s(A(O.query.tab));S(()=>O.query.tab,e=>{let t=A(e);t!==j.value&&(j.value=t,t===`shared`&&L(M.value))});let ie=[{id:`pending`,label:`Pending`},{id:`approved`,label:`Approved`},{id:`declined`,label:`Declined`}],M=s(`pending`),N=s([]),P=s(!1),F=s(1),I=s(1);async function L(e,t=1){P.value=!0;try{let n=await d.fetchSharedImages(e,t);N.value=n.items,F.value=n.page,I.value=n.totalPages}finally{P.value=!1}}function oe(e){M.value=e,L(e,1)}function R(e){L(M.value,e)}function se(e){let t=N.value.findIndex(t=>t.id===e.id);t!==-1&&(N.value[t]=e)}e(()=>{d.fetchImages(),f.fetchDevices(),d.fetchPendingCount(),j.value===`shared`&&L(M.value)});let z=s(null);function ce(){z.value?.click()}function le(e){let t=e.target,n=t.files?.[0];t.value=``,n&&(_.init(n),c.push(`/upload`))}function ue(){return window.scrollY===0}async function de(){await Promise.all([d.fetchImages({silent:!0}),d.fetchPendingCount(),f.fetchDevices({silent:!0}),j.value===`shared`?L(M.value,F.value):Promise.resolve()])}let B=m(()=>d.images),V=s(!1),H=s(null);function U(e){H.value=e,V.value=!0}let W=s(null);async function G(e,t){if(!W.value){W.value=e.id;try{await _.initEdit(e,t),c.push(`/upload`)}catch{v.show(`Could not load photo for editing`,`error`)}finally{W.value=null}}}function K(e){if(e.cropOrientation)return e.cropOrientation;let t=e.cropParams;return!t?.natW||!t?.natH?null:t.natW>=t.natH?`landscape`:`portrait`}function q(e){let t=K(e);if(!t)return null;for(let n of e.approvedDeviceIds){let e=f.devices.find(e=>e.id===n);if(e&&e.orientation!==t)return e}return null}function J(e){return f.devices.find(t=>t.lockedImageId===e.id)??null}async function Ke(e,t,n){try{await d.setApproval(e,t,n)}catch{v.show(`Failed to update frame approval`,`error`)}}async function qe(e,t,n){try{n?await f.lockImage(t,e):await f.unlockImage(t)}catch{v.show(`Failed to update lock`,`error`)}}let Y=s(!1),X=s(null),Je=m(()=>X.value===null?null:d.images.find(e=>e.id===X.value)??null);function Ye(e){X.value=e.id,Y.value=!0}function Xe(e){Ke(e.imageId,e.deviceId,e.approved)}function Ze(e){qe(e.imageId,e.deviceId,e.locked)}let Z=s(!1),Q=s(null),$=s(!1);function Qe(e){Q.value=e,Z.value=!0}async function $e(){if(Q.value){$.value=!0;try{await d.deleteImage(Q.value),Z.value=!1,v.show(`Photo deleted`,`success`)}catch{v.show(`Delete failed`,`error`)}finally{$.value=!1}}}return(e,n)=>(a(),x(`main`,me,[o(re,{"is-at-top":ue,"on-refresh":de},{default:t(()=>[p(`div`,he,[o(E,{variant:`primary`,class:`library__add-btn`,onClick:ce},{default:t(()=>[...n[6]||=[b(` + Add Photo `,-1)]]),_:1})]),p(`div`,ge,[(a(),x(h,null,r(k,e=>p(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":j.value===e.id,class:g([`library__tab`,{"library__tab--active":j.value===e.id}]),onClick:t=>j.value=e.id},l(e.label),11,_e)),64))]),i(d).loading?(a(),x(`div`,ve,`Loading…`)):j.value===`shared`?(a(),x(h,{key:2},[p(`div`,Pe,[(a(),x(h,null,r(ie,e=>p(`button`,{key:e.id,type:`button`,role:`tab`,"aria-selected":M.value===e.id,class:g([`library__subtab`,{"library__subtab--active":M.value===e.id}]),onClick:t=>oe(e.id)},l(e.label),11,Fe)),64))]),P.value?(a(),x(`div`,Ie,`Loading…`)):N.value.length===0?(a(),x(`div`,Le,[n[15]||=p(`svg`,{width:`48`,height:`48`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`,"aria-hidden":`true`},[p(`circle`,{cx:`18`,cy:`5`,r:`3`}),p(`circle`,{cx:`6`,cy:`12`,r:`3`}),p(`circle`,{cx:`18`,cy:`19`,r:`3`}),p(`line`,{x1:`8.59`,y1:`13.51`,x2:`15.42`,y2:`17.49`}),p(`line`,{x1:`15.41`,y1:`6.51`,x2:`8.59`,y2:`10.49`})],-1),p(`p`,Re,l(M.value===`pending`?`No pending photos`:M.value===`approved`?`No approved photos`:`No declined photos`),1),p(`p`,ze,l(M.value===`pending`?`Photos shared with you will appear here.`:`Photos you've added to a frame will appear here.`),1)])):(a(),x(`div`,Be,[(a(!0),x(h,null,r(N.value,e=>(a(),u(ae,{key:e.id,item:e,onUpdated:se},null,8,[`item`]))),128))])),I.value>1?(a(),x(`div`,Ve,[p(`button`,{class:`library__page-btn`,disabled:F.value<=1,onClick:n[0]||=e=>R(F.value-1)},`← Prev`,8,He),p(`span`,Ue,l(F.value)+` / `+l(I.value),1),p(`button`,{class:`library__page-btn`,disabled:F.value>=I.value,onClick:n[1]||=e=>R(F.value+1)},`Next →`,8,We)])):y(``,!0)],64)):(a(),x(h,{key:1},[B.value.length===0?(a(),x(`div`,ye,[...n[7]||=[p(`svg`,{width:`48`,height:`48`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.5`,"aria-hidden":`true`},[p(`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`}),p(`circle`,{cx:`8.5`,cy:`8.5`,r:`1.5`}),p(`polyline`,{points:`21,15 16,10 5,21`})],-1),p(`p`,{class:`library__empty-title`},`No photos yet`,-1),p(`p`,{class:`library__empty-sub`},`Tap "+ Add Photo" above to upload your first one.`,-1)]])):(a(),x(`div`,be,[(a(!0),x(h,null,r(B.value,e=>(a(),x(`div`,{key:e.id,class:`library__item`},[p(`div`,xe,[p(`img`,{src:e.thumbnailUrl,alt:e.originalFilename,class:`library__img`,loading:`lazy`},null,8,Se),J(e)?(a(),x(`div`,{key:0,class:`library__thumb-lock`,title:`Locked on ${J(e).name}`,"aria-hidden":`true`},[...n[8]||=[p(`svg`,{width:`14`,height:`14`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},[p(`rect`,{x:`3`,y:`11`,width:`18`,height:`11`,rx:`2`,ry:`2`}),p(`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`})],-1)]],8,Ce)):y(``,!0),p(`div`,we,[q(e)?(a(),x(`button`,{key:0,class:`library__action-btn library__action-btn--warn`,type:`button`,"aria-label":`Crop orientation does not match ${q(e).name}; tap to re-crop`,title:`Cropped ${K(e)}, but ${q(e).name} is set to ${q(e).orientation}.`,onClick:t=>G(e,q(e).id)},[...n[9]||=[p(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},[p(`path`,{d:`M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z`}),p(`line`,{x1:`12`,y1:`9`,x2:`12`,y2:`13`}),p(`line`,{x1:`12`,y1:`17`,x2:`12.01`,y2:`17`})],-1)]],8,Te)):y(``,!0),p(`button`,{class:`library__action-btn`,type:`button`,"aria-label":`Edit ${e.originalFilename}`,disabled:W.value===e.id,onClick:t=>G(e)},[W.value===e.id?(a(),x(`svg`,Oe,[...n[11]||=[p(`circle`,{cx:`12`,cy:`12`,r:`10`},null,-1),p(`line`,{x1:`12`,y1:`8`,x2:`12`,y2:`12`},null,-1),p(`line`,{x1:`12`,y1:`16`,x2:`12.01`,y2:`16`},null,-1)]])):(a(),x(`svg`,De,[...n[10]||=[p(`path`,{d:`M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7`},null,-1),p(`path`,{d:`M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z`},null,-1)]]))],8,Ee),p(`button`,{class:`library__action-btn`,type:`button`,"aria-label":`Share ${e.originalFilename}`,onClick:t=>U(e.id)},[...n[12]||=[p(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},[p(`circle`,{cx:`18`,cy:`5`,r:`3`}),p(`circle`,{cx:`6`,cy:`12`,r:`3`}),p(`circle`,{cx:`18`,cy:`19`,r:`3`}),p(`line`,{x1:`8.59`,y1:`13.51`,x2:`15.42`,y2:`17.49`}),p(`line`,{x1:`15.41`,y1:`6.51`,x2:`8.59`,y2:`10.49`})],-1)]],8,ke),p(`button`,{class:`library__action-btn library__action-btn--danger`,type:`button`,"aria-label":`Delete photo`,onClick:t=>Qe(e.id)},[...n[13]||=[p(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":`2.5`,"aria-hidden":`true`},[p(`polyline`,{points:`3 6 5 6 21 6`}),p(`path`,{d:`M19 6l-1 14H6L5 6`}),p(`path`,{d:`M10 11v6M14 11v6`}),p(`path`,{d:`M9 6V4h6v2`})],-1)]],8,Ae)])]),i(f).devices.length>0?(a(),x(`button`,{key:0,type:`button`,class:`library__manage`,"aria-label":`Manage frames for ${e.originalFilename}`,onClick:t=>Ye(e)},[p(`span`,Me,[p(`b`,null,l(e.approvedDeviceIds.length),1),b(`/`+l(i(f).devices.length)+` `+l(i(f).devices.length===1?`frame`:`frames`)+` `,1),J(e)?(a(),x(`span`,Ne,`· 🔒 `+l(J(e).name),1)):y(``,!0)]),n[14]||=p(`span`,{class:`library__manage-action`},`Manage ▸`,-1)],8,je)):y(``,!0)]))),128))]))],64))]),_:1}),H.value===null?y(``,!0):(a(),u(pe,{key:0,modelValue:V.value,"onUpdate:modelValue":n[2]||=e=>V.value=e,"image-id":H.value},null,8,[`modelValue`,`image-id`])),o(fe,{modelValue:Y.value,"onUpdate:modelValue":n[3]||=e=>Y.value=e,image:Je.value,devices:i(f).devices,onApproval:Xe,onLock:Ze},null,8,[`modelValue`,`image`,`devices`]),o(D,{modelValue:Z.value,"onUpdate:modelValue":n[5]||=e=>Z.value=e,label:`Delete photo`},{default:t(()=>[n[17]||=p(`h2`,{class:`library__sheet-title`},`Delete this photo?`,-1),n[18]||=p(`p`,{class:`library__sheet-sub`},`It will be removed from all frames.`,-1),p(`div`,Ge,[o(E,{variant:`secondary`,onClick:n[4]||=e=>Z.value=!1},{default:t(()=>[...n[16]||=[b(`Cancel`,-1)]]),_:1}),o(E,{variant:`destructive`,disabled:$.value,onClick:$e},{default:t(()=>[b(l($.value?`Deleting…`:`Delete`),1)]),_:1},8,[`disabled`])])]),_:1},8,[`modelValue`]),p(`input`,{ref_key:`fileInputEl`,ref:z,type:`file`,accept:`image/jpeg,image/png,image/webp,image/gif`,hidden:``,onChange:le},null,544)]))}}),[[`__scopeId`,`data-v-dd1ac7ac`]]);export{K as default}; |