@antontranelis/money-printer 1.0.84 → 1.0.85
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/dist/index.cjs +3 -3
- package/dist/index.js +134 -134
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),g=require("react"),en=require("zustand"),tn=require("zustand/middleware"),nn=require("jspdf");var ge=typeof document<"u"?document.currentScript:null;const an=1024,ct=1200,le=new Map;let F=null,lt=null;function Qe(e,t){return F||(F=document.createElement("canvas"),lt=F.getContext("2d",{willReadFrequently:!0})),(F.width!==e||F.height!==t)&&(F.width=e,F.height=t),lt}function pe(e){const t=le.get(e);return t?Promise.resolve(t):new Promise((n,a)=>{const r=new Image;r.onload=()=>{if(le.size>10){const l=le.keys().next().value;l&&le.delete(l)}le.set(e,r),n(r)},r.onerror=()=>a(new Error("Failed to load image")),r.src=e})}function rn(){le.clear()}async function pt(e,t=an){const n=await pe(e),a=Math.max(n.width,n.height);if(a<=t)return e;const r=t/a,l=Math.round(n.width*r),i=Math.round(n.height*r),s=document.createElement("canvas"),o=s.getContext("2d");if(!o)throw new Error("Failed to get canvas context");return s.width=l,s.height=i,o.drawImage(n,0,0,l,i),s.toDataURL("image/jpeg",.9)}async function ft(e){const t=await pe(e),n=Math.max(t.width,t.height);if(n<=ct){const o=document.createElement("canvas"),u=o.getContext("2d");if(!u)throw new Error("Failed to get canvas context");return o.width=t.width,o.height=t.height,u.drawImage(t,0,0),o.toDataURL("image/png")}const a=ct/n,r=Math.round(t.width*a),l=Math.round(t.height*a),i=document.createElement("canvas"),s=i.getContext("2d");if(!s)throw new Error("Failed to get canvas context");return i.width=r,i.height=l,s.drawImage(t,0,0,r,l),i.toDataURL("image/png")}async function We(e,t,n,a=0){const[r,l]=await Promise.all([pe(e),pe(t)]),i=Qe(r.width,r.height);if(i.clearRect(0,0,r.width,r.height),n>0){const s=a*20;i.save(),i.globalAlpha=n,s>0&&(i.filter=`blur(${s}px)`),i.drawImage(l,0,0,r.width,r.height),i.restore()}return i.drawImage(r,0,0),F.toDataURL("image/png")}async function bt(e,t=.5,n=40){const a=await pe(e),r=Qe(a.width,a.height);r.clearRect(0,0,a.width,a.height),r.drawImage(a,0,0);const l=r.getImageData(0,0,a.width,a.height),i=l.data,s=new Uint32Array(i.buffer),o=1+t*.8,u=1-t,h=n%360/360;for(let f=0;f<s.length;f++){const p=s[f],m=p&255,y=p>>8&255,k=p>>16&255,d=p>>24&255;if(d===0)continue;let E=(((77*m+150*y+29*k>>8)/255-.5)*o+.5)*255;E<0?E=0:E>255&&(E=255);const v=E/255,S=.12,[L,P,D]=xt(h,S,v),j=m*u+L*t|0,R=y*u+P*t|0,C=k*u+D*t|0;s[f]=d<<24|C<<16|R<<8|j}return r.putImageData(l,0,0),F.toDataURL("image/png")}function on(e,t,n){e/=255,t/=255,n/=255;const a=Math.max(e,t,n),r=Math.min(e,t,n),l=(a+r)/2;let i=0,s=0;if(a!==r){const o=a-r;switch(s=l>.5?o/(2-a-r):o/(a+r),a){case e:i=((t-n)/o+(t<n?6:0))/6;break;case t:i=((n-e)/o+2)/6;break;case n:i=((e-t)/o+4)/6;break}}return[i,s,l]}function xt(e,t,n){if(t===0){const i=Math.round(n*255);return[i,i,i]}const a=(i,s,o)=>(o<0&&(o+=1),o>1&&(o-=1),o<1/6?i+(s-i)*6*o:o<1/2?s:o<2/3?i+(s-i)*(2/3-o)*6:i),r=n<.5?n*(1+t):n+t-n*t,l=2*n-r;return[Math.round(a(l,r,e+1/3)*255),Math.round(a(l,r,e)*255),Math.round(a(l,r,e-1/3)*255)]}const sn=29,cn=5;async function wt(e,t){if(Math.abs(t-sn)<=cn)return e;const n=await pe(e),a=Qe(n.width,n.height);a.clearRect(0,0,n.width,n.height),a.drawImage(n,0,0);const r=a.getImageData(0,0,n.width,n.height),l=r.data,i=new Uint32Array(l.buffer),s=t%360/360,o=20/360,u=45/360,h=i.length;for(let f=0;f<h;f++){const p=i[f],m=p&255,y=p>>8&255,k=p>>16&255,d=p>>24&255;if(d===0)continue;const[I,E,v]=on(m,y,k);if(E<.08||I<o||I>u)continue;const S=s,L=Math.min(E,.05),[P,D,j]=xt(S,L,v);i[f]=d<<24|j<<16|D<<8|P}return a.putImageData(r,0,0),F.toDataURL("image/png")}const me=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ge&&ge.tagName.toUpperCase()==="SCRIPT"&&ge.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",X={background:`${me}templates/background.webp`,frontFrame:`${me}templates/front_frame.webp`,backFrame:`${me}templates/back_frame.webp`},he={1:`${me}templates/1.png`,5:`${me}templates/5.png`,10:`${me}templates/10.png`},yt={de:{banner:{1:"EINE STUNDE",5:"FÜNF STUNDEN",10:"ZEHN STUNDEN"}},en:{banner:{1:"ONE HOUR",5:"FIVE HOURS",10:"TEN HOURS"}}},ne=3633,ae=1920,Be=.5,ln=Math.round(ne*Be),un=Math.round(ae*Be),vt=320,kt=335,$={badges:{topLeft:{x:286,y:235},topRight:{x:3340,y:230},bottomLeft:{x:282,y:1665},bottomRight:{x:3345,y:1665}},banner:{centerX:1816,centerY:3820,radius:3610,fontSize:103,color:"#2a3a2a"}},Ee=new Map,ie=new Map,Ve=new Map,Ke=new Map,Fe=new Map;function It(e,t,n,a,r,l,i){e.save(),e.font=`900 ${l}px "Times New Roman", Georgia, serif`,e.fillStyle=i,e.textAlign="center",e.textBaseline="middle";const o=e.measureText(t).width/r,u=-Math.PI/2-o/2,h=t.split(""),f=[];for(const m of h)f.push(e.measureText(m).width);let p=u;for(let m=0;m<h.length;m++){const y=h[m],k=f[m],d=p+k/2/r,I=n+r*Math.cos(d),E=a+r*Math.sin(d);e.save(),e.translate(I,E),e.rotate(d+Math.PI/2),e.fillText(y,0,0),e.restore(),p+=k/r}e.restore()}let W={background:null,frontFrame:null,backFrame:null,badges:{1:null,5:null,10:null}};async function dn(){const[e,t,n,a,r,l]=await Promise.all([B(X.background),B(X.frontFrame),B(X.backFrame),B(he[1]),B(he[5]),B(he[10])]);W={background:e,frontFrame:t,backFrame:n,badges:{1:a,5:r,10:l}}}function gn(e,t){const n=Math.round(ne*e),a=Math.round(ae*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");l.drawImage(t,0,0,n,a);const i=e<1?.8:.95;return r.toDataURL("image/jpeg",i)}function mn(e,t){const n=Math.round(ne*e),a=Math.round(ae*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");const i=vt*e,s=kt*e,o=$.badges,u=(h,f)=>{const p=f/2,m=h.x*e-p,y=h.y*e-p;l.drawImage(t,m,y,f,f)};return u(o.topLeft,i),u(o.topRight,i),u(o.bottomLeft,s),u(o.bottomRight,s),r.toDataURL("image/png")}function Tt(e,t,n,a=1){const r=yt[n].banner[t];It(e,r,$.banner.centerX*a,$.banner.centerY*a,$.banner.radius*a,$.banner.fontSize*a,$.banner.color)}function Et(e,t,n,a,r,l,i){const s=Math.round(ne*a),o=Math.round(ae*a),u=document.createElement("canvas");u.width=s,u.height=o;const h=u.getContext("2d");if(!h)throw new Error("Failed to get canvas context");h.drawImage(r,0,0,s,o);{const p=vt*a,m=kt*a,y=$.badges,k=(d,I)=>{const E=I/2,v=d.x*a-E,S=d.y*a-E;h.drawImage(i,v,S,I,I)};k(y.topLeft,p),k(y.topRight,p),k(y.bottomLeft,m),k(y.bottomRight,m)}if(h.drawImage(l,0,0,s,o),n==="front"){const p=yt[t].banner[e];It(h,p,$.banner.centerX*a,$.banner.centerY*a,$.banner.radius*a,$.banner.fontSize*a,$.banner.color)}const f=a<1?.8:.95;return u.toDataURL("image/jpeg",f)}async function St(e,t,n){const a=`${e}-${t}-${n}`;if(Ee.has(a))return Ee.get(a);const r=W.background||await B(X.background),l=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),i=W.badges[e]||await B(he[e]),s=Et(e,t,n,Be,r,l,i);return Ee.set(a,s),s}async function qe(e,t,n){const a=`${e}-${t}-${n}`;if(ie.has(a))return ie.get(a);const r=W.background||await B(X.background),l=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),i=W.badges[e]||await B(he[e]),s=Et(e,t,n,1,r,l,i);if(ie.size>4){const o=ie.keys().next().value;o&&ie.delete(o)}return ie.set(a,s),s}function hn(){return{width:ne,height:ae}}function pn(){Ee.clear(),ie.clear(),Ve.clear(),Ke.clear(),Fe.clear()}async function Ze(e,t,n="front",a=Be){const r=`bg-${a}`;let l=Ve.get(r);if(!l){const h=W.background||await B(X.background);l=gn(a,h),Ve.set(r,l)}const i=`badges-${e}-${a}`;let s=Ke.get(i);if(!s){const h=W.badges[e]||await B(he[e]);s=mn(a,h),Ke.set(i,s)}const o=`${n}-${a}`;let u=Fe.get(o);if(!u){const h=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),f=Math.round(ne*a),p=Math.round(ae*a),m=document.createElement("canvas");m.width=f,m.height=p;const y=m.getContext("2d");if(!y)throw new Error("Failed to get canvas context");y.drawImage(h,0,0,f,p),u=m.toDataURL("image/png"),Fe.set(o,u)}return{background:l,badges:s,frame:u}}async function fn(){const e=[1,5,10],t=["de","en"],n=["front","back"],a=[];for(const r of e)for(const l of t)for(const i of n)a.push(St(r,l,i));await Promise.all(a)}const ze=new Map,se=new Map;function Pt(){se.clear()}async function B(e){return ze.has(e)?ze.get(e):new Promise((t,n)=>{const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{ze.set(e,a),t(a)},a.onerror=n,a.src=e})}function ce(e,t,n,a){e.drawImage(t,0,0,n,a)}const bn=29,xn=5;async function Lt(e,t,n,a){if(Math.abs(t-bn)<=xn)return B(e);const r=`${e}:${t}:${n}x${a}`;if(se.has(r))return B(se.get(r));const l=await B(e),i=document.createElement("canvas");i.width=n,i.height=a;const s=i.getContext("2d");if(!s)throw new Error("Failed to get canvas context");s.drawImage(l,0,0,n,a);const o=i.toDataURL("image/png"),u=await wt(o,t);if(se.size>20){const h=se.keys().next().value;h&&se.delete(h)}return se.set(r,u),B(u)}function wn(e,t,n,a,r,l="de"){e.save(),e.beginPath(),e.ellipse(t,n,a,r,0,0,Math.PI*2),e.closePath(),e.setLineDash([20,10]),e.strokeStyle="rgba(100, 100, 100, 0.4)",e.lineWidth=3,e.stroke(),e.restore()}function Rt(e,t,n,a,r,l,i=1,s=0,o=0){e.save(),e.beginPath(),e.ellipse(n,a,r,l,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,h=r/l,f=r*2,p=l*2;let m,y;u>h?(y=p,m=p*u):(m=f,y=f/u),m*=i,y*=i;const k=Math.max(0,(m-f)/2),d=Math.max(0,(y-p)/2),I=n-m/2+s*k,E=a-y/2+o*d;e.drawImage(t,I,E,m,y),e.restore()}function et(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="middle",e.fillStyle=a,n.maxWidth?e.fillText(t,n.x,n.y,n.maxWidth):e.fillText(t,n.x,n.y),e.restore()}function Ct(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="top",e.fillStyle=a;const r=n.maxWidth||400,l=n.lineHeight||n.fontSize*1.4,i=t.split(" "),s=[];let o="";for(const f of i){const p=o?`${o} ${f}`:f;e.measureText(p).width>r&&o?(s.push(o),o=f):o=p}o&&s.push(o);const u=s.length*l;let h=n.y-u/2;for(const f of s)e.fillText(f,n.x,h),h+=l;e.restore()}function Bt(e,t,n,a,r,l="#2a3a2a"){e.save(),e.font=`${r.fontSize}px "Times New Roman", serif`,e.textAlign=r.align||"center",e.textBaseline="middle",e.fillStyle=l;const i=r.lineHeight||r.fontSize*1.8,s=[t,n,a].filter(Boolean),o=(s.length-1)*i;let u=r.y-o/2;for(const h of s)h&&(e.fillText(h,r.x,u),u+=i);e.restore()}function yn(e,t,n,a="#2a3a2a"){e.save(),e.strokeStyle=a,e.lineWidth=Math.max(2,t.labelFontSize/16),e.beginPath(),e.moveTo(t.x-t.width/2,t.y),e.lineTo(t.x+t.width/2,t.y),e.stroke(),e.font=`${t.labelFontSize}px "Times New Roman", serif`,e.textAlign="center",e.textBaseline="top",e.fillStyle=a,e.fillText(n,t.x,t.y+t.labelFontSize*.3),e.restore()}async function Nt(e,t,n,a,r,l,i,s,o,u=1,h=0,f=0,p=0,m=1,y="de"){const k=e.getContext("2d");if(!k)return;const d=document.createElement("canvas");d.width=s,d.height=o;const I=d.getContext("2d");if(!I)return;I.clearRect(0,0,s,o);const E=await Lt(t,p,s,o);ce(I,E,s,o);const v=await B(n);if(ce(I,v,s,o),r)try{const P=await B(r);Rt(I,P,i.portrait.x,i.portrait.y,i.portrait.radiusX,i.portrait.radiusY,u,h,f)}catch(P){console.error("Failed to load portrait:",P)}else wn(I,i.portrait.x,i.portrait.y,i.portrait.radiusX,i.portrait.radiusY,y);const S=await B(a);ce(I,S,s,o);const L=s/3633;Tt(I,m,y,L),l&&et(I,l,i.namePlate),e.width=s,e.height=o,k.drawImage(d,0,0)}async function jt(e,t,n,a,r,l,i,s,o,u,h,f=0,p=1,m="de"){const y=e.getContext("2d");if(!y)return;const k=document.createElement("canvas");k.width=u,k.height=h;const d=k.getContext("2d");if(!d)return;d.clearRect(0,0,u,h);const I=await Lt(t,f,u,h);ce(d,I,u,h);const E=await B(n);ce(d,E,u,h);const v=await B(a);ce(d,v,u,h);const S=u/3633;if(Tt(d,p,m,S),o.contactInfo&&(r||l||i)&&Bt(d,r,l,i,o.contactInfo),o.description&&s&&Ct(d,s,o.description),r&&et(d,r,o.namePlate),o.signature){const L=m==="de"?"Unterschrift":"Signature";yn(d,o.signature,L)}e.width=u,e.height=h,y.drawImage(k,0,0)}const Pe="money-generator-portrait",Le="money-generator-bg-removed";async function vn(e){try{if(localStorage.removeItem(Pe),!e)return;const t=await ft(e);try{localStorage.setItem(Pe,t)}catch(n){console.warn("Could not persist portrait to localStorage:",n)}}catch(t){console.warn("Error processing portrait for storage:",t)}}async function kn(e){try{if(localStorage.removeItem(Le),!e)return;const t=await ft(e);try{localStorage.setItem(Le,t)}catch(n){console.warn("Could not persist bg-removed image to localStorage:",n)}}catch(t){console.warn("Error processing bg-removed image for storage:",t)}}function In(){try{return localStorage.getItem(Pe)}catch{return null}}function Tn(){try{return localStorage.getItem(Le)}catch{return null}}function En(){try{localStorage.removeItem(Pe),localStorage.removeItem(Le)}catch{}}function Sn(){return(typeof navigator<"u"?navigator.language:"de").toLowerCase().startsWith("de")?"de":"en"}const Re=Sn(),ut={personalInfo:{name:"",email:"",phone:""},voucherConfig:{hours:1,description:"",language:Re,templateHue:29},portrait:{original:null,enhanced:null,useEnhanced:!1,zoom:1,panX:0,panY:0,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:0},currentSide:"front",isEnhancing:!1,isExporting:!1,appLanguage:Re},w=en.create()(tn.persist(e=>({...ut,setPersonalInfo:t=>e(n=>({personalInfo:{...n.personalInfo,...t}})),setVoucherConfig:t=>e(n=>({voucherConfig:{...n.voucherConfig,...t}})),setPortrait:(t,n=null)=>(vn(t),e(a=>({portrait:{...a.portrait,original:t,enhanced:n,useEnhanced:!1,zoom:a.portrait.original&&t?a.portrait.zoom:1,panX:a.portrait.original&&t?a.portrait.panX:0,panY:a.portrait.original&&t?a.portrait.panY:0}}))),setEnhancedPortrait:t=>e(n=>({portrait:{...n.portrait,enhanced:t,useEnhanced:t!==null}})),toggleUseEnhanced:()=>e(t=>({portrait:{...t.portrait,useEnhanced:t.portrait.enhanced?!t.portrait.useEnhanced:!1}})),setPortraitZoom:t=>e(n=>({portrait:{...n.portrait,zoom:t}})),setPortraitPan:(t,n)=>e(a=>({portrait:{...a.portrait,panX:t,panY:n}})),setPortraitRawImage:t=>e(n=>({portrait:{...n.portrait,rawImage:t}})),setPortraitBgRemoved:(t,n)=>(n!==void 0&&kn(n),e(a=>({portrait:{...a.portrait,bgRemoved:t,bgRemovedImage:n!==void 0?n:a.portrait.bgRemovedImage}}))),setPortraitBgOpacity:t=>e(n=>({portrait:{...n.portrait,bgOpacity:t}})),setPortraitBgBlur:t=>e(n=>({portrait:{...n.portrait,bgBlur:t}})),setPortraitEngravingIntensity:t=>e(n=>({portrait:{...n.portrait,engravingIntensity:t}})),setCurrentSide:t=>e({currentSide:t}),flipSide:()=>e(t=>({currentSide:t.currentSide==="front"?"back":"front"})),setIsEnhancing:t=>e({isEnhancing:t}),setIsExporting:t=>e({isExporting:t}),setAppLanguage:t=>e({appLanguage:t}),setBillLanguage:t=>e(n=>({voucherConfig:{...n.voucherConfig,language:t}})),setHours:t=>e(n=>({voucherConfig:{...n.voucherConfig,hours:t}})),setTemplateHue:t=>(Pt(),e(n=>({voucherConfig:{...n.voucherConfig,templateHue:t}}))),reset:()=>(En(),e(ut))}),{name:"money-generator-storage",migrate:e=>{const t=e;return t!=null&&t.voucherConfig&&(t.voucherConfig.templateHue===void 0&&(t.voucherConfig.templateHue=29),t.voucherConfig.hours=1,t.voucherConfig.language=Re),t&&(t.appLanguage=Re),t},version:2,partialize:e=>({personalInfo:e.personalInfo,voucherConfig:{...e.voucherConfig},appLanguage:e.appLanguage,portrait:{original:null,enhanced:null,useEnhanced:e.portrait.useEnhanced,zoom:e.portrait.zoom,panX:e.portrait.panX,panY:e.portrait.panY,rawImage:null,bgRemovedImage:null,bgRemoved:e.portrait.bgRemoved,bgOpacity:e.portrait.bgOpacity,bgBlur:e.portrait.bgBlur,engravingIntensity:e.portrait.engravingIntensity},currentSide:"front",isEnhancing:!1,isExporting:!1})}));if(typeof window<"u"){const e=In(),t=Tn();e&&setTimeout(()=>{const n=w.getState();if(!n.portrait.original){const a=n.portrait.bgRemoved,r=t!==null;w.setState({portrait:{...n.portrait,original:e,rawImage:e,bgRemovedImage:t,bgRemoved:a&&r,bgOpacity:a&&r?n.portrait.bgOpacity:0,bgBlur:a&&r?n.portrait.bgBlur:0}})}},0)}const Pn={header:{title:"Money Generator",subtitle:"Erstelle deinen persönlichen Zeitgutschein"},form:{personalInfo:{title:"Persönliche Daten",name:"Name",namePlaceholder:"Dein Name",email:"E-Mail",emailPlaceholder:"deine@email.de",phone:"Telefon",phonePlaceholder:"+49 123 456789"},portrait:{title:"Portrait",upload:"Bild hochladen",dragDrop:"oder hierher ziehen",enhance:"Mit AI verbessern",enhancing:"Wird verbessert...",useOriginal:"Original verwenden",useEnhanced:"Verbessertes verwenden",zoom:"Zoom"},voucher:{title:"Gutschein",hours:"Stunden",hourLabel:"Stunde",hoursLabel:"Stunden",description:"Beschreibung",descriptionPlaceholder:"Was kann mit diesem Gutschein eingelöst werden?",billLanguage:"Schein-Sprache",billLanguageGerman:"Deutsch",billLanguageEnglish:"Englisch"},billColor:{title:"Scheinfarbe",label:"Farbton"}},preview:{front:"Vorderseite",back:"Rückseite",flip:"Umdrehen"},export:{button:"Als PDF herunterladen",exporting:"PDF wird erstellt...",success:"Download gestartet!"},bill:{descriptionText:"Für diesen Schein erhältst du {bannerText} meiner Zeit oder ein gleichwertiges Dankeschön.",bannerText:{1:"eine Stunde",5:"fünf Stunden",10:"zehn Stunden"}}},Ln={header:{title:"Money Generator",subtitle:"Create your personal time voucher"},form:{personalInfo:{title:"Personal Information",name:"Name",namePlaceholder:"Your name",email:"Email",emailPlaceholder:"your@email.com",phone:"Phone",phonePlaceholder:"+1 234 567890"},portrait:{title:"Portrait",upload:"Upload image",dragDrop:"or drag and drop",enhance:"Enhance with AI",enhancing:"Enhancing...",useOriginal:"Use original",useEnhanced:"Use enhanced",zoom:"Zoom"},voucher:{title:"Voucher",hours:"Hours",hourLabel:"hour",hoursLabel:"hours",description:"Description",descriptionPlaceholder:"What can be redeemed with this voucher?",billLanguage:"Bill Language",billLanguageGerman:"German",billLanguageEnglish:"English"},billColor:{title:"Bill Color",label:"Hue"}},preview:{front:"Front",back:"Back",flip:"Flip"},export:{button:"Download as PDF",exporting:"Creating PDF...",success:"Download started!"},bill:{descriptionText:"For this voucher, you will receive {bannerText} of my time or an equivalent appreciation in return.",bannerText:{1:"one hour",5:"five hours",10:"ten hours"}}},Rn={de:Pn,en:Ln};function re(e){return Rn[e]}function tt(e,t,n){if(n&&n.trim())return n;const a=re(e),r=a.bill.bannerText[t]||a.bill.bannerText[1];return a.bill.descriptionText.replace("{bannerText}",r)}function Cn(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}function Bn(e){return e.replace(/\D/g,"").length>=6}function Nn({focusField:e,onFocused:t,onFormFocusChange:n}={}){const a=w(d=>d.appLanguage),r=w(d=>d.personalInfo),l=w(d=>d.setPersonalInfo),i=re(a),[s,o]=g.useState(!1),[u,h]=g.useState(!1),f=s&&r.email.trim()&&!Cn(r.email),p=u&&r.phone.trim()&&!Bn(r.phone),m=g.useRef(null),y=g.useRef(null),k=g.useRef(null);return g.useEffect(()=>{if(e){const d=e==="name"?m:e==="email"?y:k;setTimeout(()=>{var I,E;(I=d.current)==null||I.click(),(E=d.current)==null||E.focus(),setTimeout(()=>{var v;(v=d.current)==null||v.scrollIntoView({behavior:"smooth",block:"center"})},300),t==null||t()},100)}},[e,t]),c.jsxs("div",{className:"space-y-4",children:[c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.name})}),c.jsx("input",{ref:m,type:"text",name:"name",autoComplete:"name",placeholder:i.form.personalInfo.namePlaceholder,className:"input input-bordered w-full input-md",value:r.name,onChange:d=>l({name:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>n==null?void 0:n(!1)})]}),c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.email})}),c.jsx("input",{ref:y,type:"email",name:"email",autoComplete:"email",placeholder:i.form.personalInfo.emailPlaceholder,className:`input input-bordered w-full input-md ${f?"input-error":""}`,value:r.email,onChange:d=>l({email:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>{o(!0),n==null||n(!1)}}),f&&c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt text-error",children:a==="de"?"Bitte gib eine gültige E-Mail-Adresse ein":"Please enter a valid email address"})})]}),c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.phone})}),c.jsx("input",{ref:k,type:"tel",name:"phone",autoComplete:"tel",placeholder:i.form.personalInfo.phonePlaceholder,className:`input input-bordered w-full input-md ${p?"input-error":""}`,value:r.phone,onChange:d=>l({phone:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>{h(!0),n==null||n(!1)}}),p&&c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt text-error",children:a==="de"?"Bitte gib eine gültige Telefonnummer ein":"Please enter a valid phone number"})})]})]})}const $e={},jn="https://api.stability.ai/v1/generation",An="https://api.stability.ai/v2beta/stable-image/edit/remove-background",At="stability_api_key";let fe=null;function Dn(e){fe=e}function Hn(){return fe}function Mn(){return fe!==null}const Un={vintage:"portrait in the style of vintage currency engraving, fine line work, crosshatching, sepia tones, detailed stippling, classic bank note portrait style",engraved:"portrait as detailed intaglio engraving, currency bill style, fine parallel lines, high contrast, official government portrait",currency:"portrait rendered as US dollar bill engraving, official currency portrait style, green tint, fine line engraving technique"},dt=[{width:1024,height:1024},{width:1152,height:896},{width:1216,height:832},{width:1344,height:768},{width:1536,height:640},{width:640,height:1536},{width:768,height:1344},{width:832,height:1216},{width:896,height:1152}];function On(e,t){const n=e/t;let a=dt[0],r=1/0;for(const l of dt){const i=l.width/l.height,s=Math.abs(n-i);s<r&&(r=s,a=l)}return a}function Yn(e){return new Promise((t,n)=>{const a=new Image;a.onload=()=>{const r=On(a.width,a.height),l=document.createElement("canvas");l.width=r.width,l.height=r.height;const i=l.getContext("2d");if(!i){n(new Error("Failed to get canvas context"));return}const s=a.width/a.height,o=r.width/r.height;let u=0,h=0,f=a.width,p=a.height;s>o?(f=a.height*o,u=(a.width-f)/2):(p=a.width/o,h=(a.height-p)/2),i.drawImage(a,u,h,f,p,0,0,r.width,r.height),t(l.toDataURL("image/png"))},a.onerror=()=>n(new Error("Failed to load image")),a.src=e})}function Dt(e){var i;const t=e.split(","),n=((i=t[0].match(/:(.*?);/))==null?void 0:i[1])||"image/png",a=atob(t[1]),r=a.length,l=new Uint8Array(r);for(let s=0;s<r;s++)l[s]=a.charCodeAt(s);return new Blob([l],{type:n})}function Ne(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ge&&ge.tagName.toUpperCase()==="SCRIPT"&&ge.src||new URL("index.cjs",document.baseURI).href}<"u"&&($e==null?void 0:$e.VITE_STABILITY_API_KEY)||typeof process<"u"&&((t=process.env)==null?void 0:t.NEXT_PUBLIC_STABILITY_API_KEY);return e&&e!=="your-api-key-here"?e:typeof localStorage<"u"?localStorage.getItem(At):null}function Ht(e){localStorage.setItem(At,e)}function Se(){return fe?!0:Ne()!==null}async function _n(e){const t=Ne();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:a,strength:r=.35}=e,l=await Yn(n),i=Dt(l),s=new FormData;s.append("init_image",i,"portrait.png"),s.append("init_image_mode","IMAGE_STRENGTH"),s.append("image_strength",String(1-r)),s.append("text_prompts[0][text]",Un[a]),s.append("text_prompts[0][weight]","1"),s.append("cfg_scale","7"),s.append("samples","1"),s.append("steps","30");const u=await fetch(`${jn}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:s});if(!u.ok){const f=await u.text();throw console.error("Stability AI error:",f),u.status===401?new Error("Invalid API key"):u.status===402?new Error("Insufficient credits"):u.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${u.status}`)}const h=await u.json();if(!h.artifacts||h.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${h.artifacts[0].base64}`}async function Mt(e){if(fe){const i=await fetch(fe,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!i.ok){const o=await i.json().catch(()=>({}));throw new Error(o.error||`API error: ${i.status}`)}return(await i.json()).imageDataUrl}const t=Ne();if(!t)throw new Error("No Stability AI API key configured");const n=Dt(e),a=new FormData;a.append("image",n,"image.png"),a.append("output_format","png");const r=await fetch(An,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:a});if(!r.ok){const i=await r.text();throw console.error("Stability AI remove background error:",i),r.status===401?new Error("Invalid API key"):r.status===402?new Error("Insufficient credits"):r.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${r.status}`)}const l=await r.blob();return new Promise((i,s)=>{const o=new FileReader;o.onload=()=>i(o.result),o.onerror=()=>s(new Error("Failed to read result")),o.readAsDataURL(l)})}function Wn(){const[e,t]=g.useState(!1),[n,a]=g.useState(!1),[r,l]=g.useState(null),[i,s]=g.useState(()=>Se());g.useEffect(()=>{s(Se());const p=setTimeout(()=>{s(Se())},150);return()=>clearTimeout(p)},[]);const o=g.useCallback(()=>l(null),[]),u=g.useCallback(p=>{Ht(p),s(!0),l(null)},[]),h=g.useCallback(async(p,m=.5,y=40)=>{t(!0),l(null);try{return await bt(p,m,y)}catch(k){const d=k instanceof Error?k.message:"Enhancement failed";throw l(d),k}finally{t(!1)}},[]),f=g.useCallback(async p=>{a(!0),l(null);try{return await Mt(p)}catch(m){const y=m instanceof Error?m.message:"Background removal failed";throw l(y),m}finally{a(!1)}},[]);return{enhance:h,removeBg:f,isEnhancing:e,isRemovingBg:n,error:r,hasKey:i,setApiKey:u,clearError:o}}function Ut({isOpen:e,onClose:t,onSubmit:n}){const a=w(u=>u.appLanguage),[r,l]=g.useState("");if(!e)return null;const i=u=>{u.preventDefault(),r.trim()&&(n(r.trim()),l(""),t())},o={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[a];return c.jsxs("dialog",{className:"modal modal-open",children:[c.jsxs("div",{className:"modal-box",children:[c.jsx("h3",{className:"font-bold text-lg",children:o.title}),c.jsx("p",{className:"py-4 text-sm opacity-80",children:o.description}),c.jsxs("form",{onSubmit:i,children:[c.jsxs("div",{className:"form-control",children:[c.jsx("input",{type:"password",placeholder:o.placeholder,className:"input input-bordered w-full",value:r,onChange:u=>l(u.target.value),autoFocus:!0}),c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt",children:o.hint})})]}),c.jsxs("div",{className:"modal-action",children:[c.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:o.cancel}),c.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!r.trim(),children:o.submit})]})]})]}),c.jsx("form",{method:"dialog",className:"modal-backdrop",children:c.jsx("button",{onClick:t,children:"close"})})]})}function ye({min:e,max:t,step:n,value:a,onChange:r,className:l="",disabled:i=!1}){const s=g.useRef(null),o=g.useRef(null),u=g.useRef(!1),[h,f]=g.useState(!1),p=(a-e)/(t-e)*100,m=g.useCallback(v=>{if(!s.current)return a;const S=s.current.getBoundingClientRect(),L=Math.max(0,Math.min(1,(v-S.left)/S.width)),P=t-e,D=e+L*P,j=Math.round(D/n)*n;return Math.max(e,Math.min(t,j))},[e,t,n,a]),y=g.useCallback(v=>{if(i)return;const S=v.touches[0];o.current={x:S.clientX,y:S.clientY,value:a,decided:!1},u.current=!1},[a,i]),k=g.useCallback(v=>{if(i||!o.current)return;const S=v.touches[0],L=Math.abs(S.clientX-o.current.x),P=Math.abs(S.clientY-o.current.y);if(!o.current.decided){if(L<8&&P<8)return;if(o.current.decided=!0,P>L){o.current=null;return}u.current=!0,f(!0)}if(u.current){const D=m(S.clientX);D!==a&&r(D)}},[i,m,r,a]),d=g.useCallback(v=>{if(o.current&&!o.current.decided){const S=v.changedTouches[0];if(S){const L=m(S.clientX);L!==a&&r(L)}}o.current=null,u.current=!1,f(!1)},[m,r,a]);g.useEffect(()=>{const v=s.current;if(!v)return;const S=L=>{u.current&&L.preventDefault()};return v.addEventListener("touchmove",S,{passive:!1}),()=>{v.removeEventListener("touchmove",S)}},[]);const I=g.useCallback(v=>{if(i)return;const S=m(v.clientX);r(S),f(!0);const L=D=>{const j=m(D.clientX);r(j)},P=()=>{f(!1),document.removeEventListener("mousemove",L),document.removeEventListener("mouseup",P)};document.addEventListener("mousemove",L),document.addEventListener("mouseup",P)},[i,m,r]),E=`calc(10px + (100% - 20px) * ${p/100})`;return c.jsxs("div",{ref:s,className:`relative h-10 flex items-center cursor-pointer overflow-visible ${i?"opacity-50 cursor-not-allowed":""}`,onTouchStart:y,onTouchMove:k,onTouchEnd:d,onMouseDown:I,children:[c.jsx("div",{className:"absolute h-2 bg-base-300 rounded-full inset-x-0"}),c.jsx("div",{className:`absolute h-2 rounded-full transition-colors ${l.includes("range-primary")?"bg-primary":l.includes("range-secondary")?"bg-secondary":"bg-primary"}`,style:{left:0,width:E}}),c.jsx("div",{className:`absolute w-5 h-5 rounded-full bg-base-100 border-2 shadow-md transition-transform ${h?"scale-110":""} ${l.includes("range-primary")?"border-primary":l.includes("range-secondary")?"border-secondary":"border-primary"}`,style:{left:E,transform:"translateX(-50%)"}})]})}function zn(){const e=w(b=>b.appLanguage),t=w(b=>b.portrait),n=w(b=>b.setPortrait),a=w(b=>b.setPortraitZoom),r=w(b=>b.setPortraitPan),l=w(b=>b.setPortraitRawImage),i=w(b=>b.setPortraitBgRemoved),s=w(b=>b.setPortraitBgOpacity),o=w(b=>b.setPortraitBgBlur),u=w(b=>b.setPortraitEngravingIntensity),{enhance:h,removeBg:f,isEnhancing:p,isRemovingBg:m,error:y,hasKey:k,setApiKey:d}=Wn(),I=re(e),E=g.useRef(null),[v,S]=g.useState(!1),[L,P]=g.useState(!1),D=g.useRef(null),j=g.useRef(null),R=t.rawImage,C=t.bgRemovedImage,Y=t.bgRemoved,q=t.bgOpacity,H=t.bgBlur,O=t.engravingIntensity;g.useEffect(()=>{t.original&&!t.rawImage&&l(t.original)},[t.original,t.rawImage,l]),g.useEffect(()=>()=>{D.current&&clearTimeout(D.current),j.current&&clearTimeout(j.current)},[]);const Z=w(b=>b.voucherConfig.templateHue),oe=g.useRef(Z),J=g.useCallback(async b=>{if(!b.type.startsWith("image/"))return;const T=new FileReader;T.onload=async M=>{var _;const A=(_=M.target)==null?void 0:_.result,V=await pt(A);rn(),l(V),n(V),a(1),r(0,0),i(!1,null),s(0),o(0),u(0)},T.readAsDataURL(b)},[n,l,a,r,i,s,o,u]),be=g.useCallback(b=>{b.preventDefault(),S(!1);const T=b.dataTransfer.files[0];T&&J(T)},[J]),G=g.useCallback(b=>{b.preventDefault(),S(!0)},[]),Q=g.useCallback(b=>{b.preventDefault(),S(!1)},[]),K=()=>{var b;(b=E.current)==null||b.click()},xe=b=>{var M;const T=(M=b.target.files)==null?void 0:M[0];T&&J(T)},ee=g.useCallback(async(b,T,M)=>{try{return await h(b,T,M)}catch(A){return console.error("Enhancement failed:",A),b}},[h]),ve=g.useCallback(async b=>{try{const T=await f(b);return i(!0,T),T}catch(T){return console.error("Background removal failed:",T),b}},[f,i]),te=g.useCallback(async()=>{const b=w.getState(),T=b.portrait,M=b.voucherConfig.templateHue;if(!T.rawImage)return;let A;T.bgRemoved&&T.bgRemovedImage?A=await We(T.bgRemovedImage,T.rawImage,T.bgOpacity,T.bgBlur):A=T.rawImage,T.engravingIntensity>0&&(A=await ee(A,T.engravingIntensity,M)),n(A)},[ee,n]);g.useEffect(()=>{if(oe.current===Z)return;oe.current=Z;const b=w.getState().portrait;b.engravingIntensity>0&&b.rawImage&&(D.current&&clearTimeout(D.current),D.current=setTimeout(te,150))},[Z,te]);const De=async()=>{if(!R)return;if(!Y&&!k){P(!0);return}if(!Y){const T=await ve(R),M=w.getState(),A=M.portrait,V=M.voucherConfig.templateHue;let _=await We(T,R,A.bgOpacity,A.bgBlur);A.engravingIntensity>0&&(_=await ee(_,A.engravingIntensity,V)),n(_)}else{i(!1,null);const T=w.getState(),M=T.portrait.engravingIntensity,A=T.voucherConfig.templateHue;if(M>0){const V=await ee(R,M,A);n(V)}else n(R)}},we=b=>{u(b),D.current&&clearTimeout(D.current),R&&(D.current=setTimeout(te,150))},He=async b=>{if(d(b),!R)return;const T=await ve(R),M=w.getState(),A=M.portrait,V=M.voucherConfig.templateHue;let _=await We(T,R,A.bgOpacity,A.bgBlur);A.engravingIntensity>0&&(_=await ee(_,A.engravingIntensity,V)),n(_)},ke=b=>{s(b),j.current&&clearTimeout(j.current),!(!R||!C)&&(j.current=setTimeout(te,150))},Ie=b=>{o(b),j.current&&clearTimeout(j.current),!(!R||!C)&&(j.current=setTimeout(te,150))};return c.jsxs("div",{className:"space-y-4",children:[c.jsx("style",{children:`
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),g=require("react"),tn=require("zustand"),nn=require("zustand/middleware"),an=require("jspdf");var ge=typeof document<"u"?document.currentScript:null;const rn=1024,ct=1200,le=new Map;let F=null,lt=null;function Qe(e,t){return F||(F=document.createElement("canvas"),lt=F.getContext("2d",{willReadFrequently:!0})),(F.width!==e||F.height!==t)&&(F.width=e,F.height=t),lt}function pe(e){const t=le.get(e);return t?Promise.resolve(t):new Promise((n,a)=>{const r=new Image;r.onload=()=>{if(le.size>10){const l=le.keys().next().value;l&&le.delete(l)}le.set(e,r),n(r)},r.onerror=()=>a(new Error("Failed to load image")),r.src=e})}function on(){le.clear()}async function pt(e,t=rn){const n=await pe(e),a=Math.max(n.width,n.height);if(a<=t)return e;const r=t/a,l=Math.round(n.width*r),i=Math.round(n.height*r),s=document.createElement("canvas"),o=s.getContext("2d");if(!o)throw new Error("Failed to get canvas context");return s.width=l,s.height=i,o.drawImage(n,0,0,l,i),s.toDataURL("image/jpeg",.9)}async function ft(e){const t=await pe(e),n=Math.max(t.width,t.height);if(n<=ct){const o=document.createElement("canvas"),u=o.getContext("2d");if(!u)throw new Error("Failed to get canvas context");return o.width=t.width,o.height=t.height,u.drawImage(t,0,0),o.toDataURL("image/png")}const a=ct/n,r=Math.round(t.width*a),l=Math.round(t.height*a),i=document.createElement("canvas"),s=i.getContext("2d");if(!s)throw new Error("Failed to get canvas context");return i.width=r,i.height=l,s.drawImage(t,0,0,r,l),i.toDataURL("image/png")}async function ze(e,t,n,a=0){const[r,l]=await Promise.all([pe(e),pe(t)]),i=Qe(r.width,r.height);if(i.clearRect(0,0,r.width,r.height),n>0){const s=a*20;i.save(),i.globalAlpha=n,s>0&&(i.filter=`blur(${s}px)`),i.drawImage(l,0,0,r.width,r.height),i.restore()}return i.drawImage(r,0,0),F.toDataURL("image/png")}async function bt(e,t=.5,n=40){const a=await pe(e),r=Qe(a.width,a.height);r.clearRect(0,0,a.width,a.height),r.drawImage(a,0,0);const l=r.getImageData(0,0,a.width,a.height),i=l.data,s=new Uint32Array(i.buffer),o=1+t*.8,u=1-t,h=n%360/360;for(let f=0;f<s.length;f++){const p=s[f],m=p&255,y=p>>8&255,k=p>>16&255,d=p>>24&255;if(d===0)continue;let E=(((77*m+150*y+29*k>>8)/255-.5)*o+.5)*255;E<0?E=0:E>255&&(E=255);const v=E/255,S=.12,[L,P,D]=xt(h,S,v),j=m*u+L*t|0,R=y*u+P*t|0,C=k*u+D*t|0;s[f]=d<<24|C<<16|R<<8|j}return r.putImageData(l,0,0),F.toDataURL("image/png")}function sn(e,t,n){e/=255,t/=255,n/=255;const a=Math.max(e,t,n),r=Math.min(e,t,n),l=(a+r)/2;let i=0,s=0;if(a!==r){const o=a-r;switch(s=l>.5?o/(2-a-r):o/(a+r),a){case e:i=((t-n)/o+(t<n?6:0))/6;break;case t:i=((n-e)/o+2)/6;break;case n:i=((e-t)/o+4)/6;break}}return[i,s,l]}function xt(e,t,n){if(t===0){const i=Math.round(n*255);return[i,i,i]}const a=(i,s,o)=>(o<0&&(o+=1),o>1&&(o-=1),o<1/6?i+(s-i)*6*o:o<1/2?s:o<2/3?i+(s-i)*(2/3-o)*6:i),r=n<.5?n*(1+t):n+t-n*t,l=2*n-r;return[Math.round(a(l,r,e+1/3)*255),Math.round(a(l,r,e)*255),Math.round(a(l,r,e-1/3)*255)]}const cn=29,ln=5;async function wt(e,t){if(Math.abs(t-cn)<=ln)return e;const n=await pe(e),a=Qe(n.width,n.height);a.clearRect(0,0,n.width,n.height),a.drawImage(n,0,0);const r=a.getImageData(0,0,n.width,n.height),l=r.data,i=new Uint32Array(l.buffer),s=t%360/360,o=20/360,u=45/360,h=i.length;for(let f=0;f<h;f++){const p=i[f],m=p&255,y=p>>8&255,k=p>>16&255,d=p>>24&255;if(d===0)continue;const[I,E,v]=sn(m,y,k);if(E<.08||I<o||I>u)continue;const S=s,L=Math.min(E,.05),[P,D,j]=xt(S,L,v);i[f]=d<<24|j<<16|D<<8|P}return a.putImageData(r,0,0),F.toDataURL("image/png")}const me=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ge&&ge.tagName.toUpperCase()==="SCRIPT"&&ge.src||new URL("index.cjs",document.baseURI).href}<"u"&&"/"||"/",X={background:`${me}templates/background.webp`,frontFrame:`${me}templates/front_frame.webp`,backFrame:`${me}templates/back_frame.webp`},he={1:`${me}templates/1.png`,5:`${me}templates/5.png`,10:`${me}templates/10.png`},yt={de:{banner:{1:"EINE STUNDE",5:"FÜNF STUNDEN",10:"ZEHN STUNDEN"}},en:{banner:{1:"ONE HOUR",5:"FIVE HOURS",10:"TEN HOURS"}}},ne=3633,ae=1920,Ne=.5,un=Math.round(ne*Ne),dn=Math.round(ae*Ne),vt=320,kt=335,$={badges:{topLeft:{x:286,y:235},topRight:{x:3340,y:230},bottomLeft:{x:282,y:1665},bottomRight:{x:3345,y:1665}},banner:{centerX:1816,centerY:3820,radius:3610,fontSize:103,color:"#2a3a2a"}},Ee=new Map,ie=new Map,Ve=new Map,Ke=new Map,Fe=new Map;function It(e,t,n,a,r,l,i){e.save(),e.font=`900 ${l}px "Times New Roman", Georgia, serif`,e.fillStyle=i,e.textAlign="center",e.textBaseline="middle";const o=e.measureText(t).width/r,u=-Math.PI/2-o/2,h=t.split(""),f=[];for(const m of h)f.push(e.measureText(m).width);let p=u;for(let m=0;m<h.length;m++){const y=h[m],k=f[m],d=p+k/2/r,I=n+r*Math.cos(d),E=a+r*Math.sin(d);e.save(),e.translate(I,E),e.rotate(d+Math.PI/2),e.fillText(y,0,0),e.restore(),p+=k/r}e.restore()}let W={background:null,frontFrame:null,backFrame:null,badges:{1:null,5:null,10:null}};async function gn(){const[e,t,n,a,r,l]=await Promise.all([B(X.background),B(X.frontFrame),B(X.backFrame),B(he[1]),B(he[5]),B(he[10])]);W={background:e,frontFrame:t,backFrame:n,badges:{1:a,5:r,10:l}}}function mn(e,t){const n=Math.round(ne*e),a=Math.round(ae*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");l.drawImage(t,0,0,n,a);const i=e<1?.8:.95;return r.toDataURL("image/jpeg",i)}function hn(e,t){const n=Math.round(ne*e),a=Math.round(ae*e),r=document.createElement("canvas");r.width=n,r.height=a;const l=r.getContext("2d");if(!l)throw new Error("Failed to get canvas context");const i=vt*e,s=kt*e,o=$.badges,u=(h,f)=>{const p=f/2,m=h.x*e-p,y=h.y*e-p;l.drawImage(t,m,y,f,f)};return u(o.topLeft,i),u(o.topRight,i),u(o.bottomLeft,s),u(o.bottomRight,s),r.toDataURL("image/png")}function Tt(e,t,n,a=1){const r=yt[n].banner[t];It(e,r,$.banner.centerX*a,$.banner.centerY*a,$.banner.radius*a,$.banner.fontSize*a,$.banner.color)}function Et(e,t,n,a,r,l,i){const s=Math.round(ne*a),o=Math.round(ae*a),u=document.createElement("canvas");u.width=s,u.height=o;const h=u.getContext("2d");if(!h)throw new Error("Failed to get canvas context");h.drawImage(r,0,0,s,o);{const p=vt*a,m=kt*a,y=$.badges,k=(d,I)=>{const E=I/2,v=d.x*a-E,S=d.y*a-E;h.drawImage(i,v,S,I,I)};k(y.topLeft,p),k(y.topRight,p),k(y.bottomLeft,m),k(y.bottomRight,m)}if(h.drawImage(l,0,0,s,o),n==="front"){const p=yt[t].banner[e];It(h,p,$.banner.centerX*a,$.banner.centerY*a,$.banner.radius*a,$.banner.fontSize*a,$.banner.color)}const f=a<1?.8:.95;return u.toDataURL("image/jpeg",f)}async function St(e,t,n){const a=`${e}-${t}-${n}`;if(Ee.has(a))return Ee.get(a);const r=W.background||await B(X.background),l=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),i=W.badges[e]||await B(he[e]),s=Et(e,t,n,Ne,r,l,i);return Ee.set(a,s),s}async function qe(e,t,n){const a=`${e}-${t}-${n}`;if(ie.has(a))return ie.get(a);const r=W.background||await B(X.background),l=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),i=W.badges[e]||await B(he[e]),s=Et(e,t,n,1,r,l,i);if(ie.size>4){const o=ie.keys().next().value;o&&ie.delete(o)}return ie.set(a,s),s}function pn(){return{width:ne,height:ae}}function Pt(){Ee.clear(),ie.clear(),Ve.clear(),Ke.clear(),Fe.clear()}async function Ze(e,t,n="front",a=Ne){const r=`bg-${a}`;let l=Ve.get(r);if(!l){const h=W.background||await B(X.background);l=mn(a,h),Ve.set(r,l)}const i=`badges-${e}-${a}`;let s=Ke.get(i);if(!s){const h=W.badges[e]||await B(he[e]);s=hn(a,h),Ke.set(i,s)}const o=`${n}-${a}`;let u=Fe.get(o);if(!u){const h=n==="front"?W.frontFrame||await B(X.frontFrame):W.backFrame||await B(X.backFrame),f=Math.round(ne*a),p=Math.round(ae*a),m=document.createElement("canvas");m.width=f,m.height=p;const y=m.getContext("2d");if(!y)throw new Error("Failed to get canvas context");y.drawImage(h,0,0,f,p),u=m.toDataURL("image/png"),Fe.set(o,u)}return{background:l,badges:s,frame:u}}async function fn(){const e=[1,5,10],t=["de","en"],n=["front","back"],a=[];for(const r of e)for(const l of t)for(const i of n)a.push(St(r,l,i));await Promise.all(a)}const Se=new Map,se=new Map;function Lt(){se.clear(),Se.clear()}async function B(e){return Se.has(e)?Se.get(e):new Promise((t,n)=>{const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{Se.set(e,a),t(a)},a.onerror=n,a.src=e})}function ce(e,t,n,a){e.drawImage(t,0,0,n,a)}const bn=29,xn=5;async function Rt(e,t,n,a){if(Math.abs(t-bn)<=xn)return B(e);const r=`${e}:${t}:${n}x${a}`;if(se.has(r))return B(se.get(r));const l=await B(e),i=document.createElement("canvas");i.width=n,i.height=a;const s=i.getContext("2d");if(!s)throw new Error("Failed to get canvas context");s.drawImage(l,0,0,n,a);const o=i.toDataURL("image/png"),u=await wt(o,t);if(se.size>20){const h=se.keys().next().value;h&&se.delete(h)}return se.set(r,u),B(u)}function wn(e,t,n,a,r,l="de"){e.save(),e.beginPath(),e.ellipse(t,n,a,r,0,0,Math.PI*2),e.closePath(),e.setLineDash([20,10]),e.strokeStyle="rgba(100, 100, 100, 0.4)",e.lineWidth=3,e.stroke(),e.restore()}function Ct(e,t,n,a,r,l,i=1,s=0,o=0){e.save(),e.beginPath(),e.ellipse(n,a,r,l,0,0,Math.PI*2),e.closePath(),e.clip();const u=t.width/t.height,h=r/l,f=r*2,p=l*2;let m,y;u>h?(y=p,m=p*u):(m=f,y=f/u),m*=i,y*=i;const k=Math.max(0,(m-f)/2),d=Math.max(0,(y-p)/2),I=n-m/2+s*k,E=a-y/2+o*d;e.drawImage(t,I,E,m,y),e.restore()}function et(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="middle",e.fillStyle=a,n.maxWidth?e.fillText(t,n.x,n.y,n.maxWidth):e.fillText(t,n.x,n.y),e.restore()}function Bt(e,t,n,a="#2a3a2a"){e.save(),e.font=`${n.fontSize}px "Times New Roman", serif`,e.textAlign=n.align||"center",e.textBaseline="top",e.fillStyle=a;const r=n.maxWidth||400,l=n.lineHeight||n.fontSize*1.4,i=t.split(" "),s=[];let o="";for(const f of i){const p=o?`${o} ${f}`:f;e.measureText(p).width>r&&o?(s.push(o),o=f):o=p}o&&s.push(o);const u=s.length*l;let h=n.y-u/2;for(const f of s)e.fillText(f,n.x,h),h+=l;e.restore()}function Nt(e,t,n,a,r,l="#2a3a2a"){e.save(),e.font=`${r.fontSize}px "Times New Roman", serif`,e.textAlign=r.align||"center",e.textBaseline="middle",e.fillStyle=l;const i=r.lineHeight||r.fontSize*1.8,s=[t,n,a].filter(Boolean),o=(s.length-1)*i;let u=r.y-o/2;for(const h of s)h&&(e.fillText(h,r.x,u),u+=i);e.restore()}function yn(e,t,n,a="#2a3a2a"){e.save(),e.strokeStyle=a,e.lineWidth=Math.max(2,t.labelFontSize/16),e.beginPath(),e.moveTo(t.x-t.width/2,t.y),e.lineTo(t.x+t.width/2,t.y),e.stroke(),e.font=`${t.labelFontSize}px "Times New Roman", serif`,e.textAlign="center",e.textBaseline="top",e.fillStyle=a,e.fillText(n,t.x,t.y+t.labelFontSize*.3),e.restore()}async function jt(e,t,n,a,r,l,i,s,o,u=1,h=0,f=0,p=0,m=1,y="de"){const k=e.getContext("2d");if(!k)return;const d=document.createElement("canvas");d.width=s,d.height=o;const I=d.getContext("2d");if(!I)return;I.clearRect(0,0,s,o);const E=await Rt(t,p,s,o);ce(I,E,s,o);const v=await B(n);if(ce(I,v,s,o),r)try{const P=await B(r);Ct(I,P,i.portrait.x,i.portrait.y,i.portrait.radiusX,i.portrait.radiusY,u,h,f)}catch(P){console.error("Failed to load portrait:",P)}else wn(I,i.portrait.x,i.portrait.y,i.portrait.radiusX,i.portrait.radiusY,y);const S=await B(a);ce(I,S,s,o);const L=s/3633;Tt(I,m,y,L),l&&et(I,l,i.namePlate),e.width=s,e.height=o,k.drawImage(d,0,0)}async function At(e,t,n,a,r,l,i,s,o,u,h,f=0,p=1,m="de"){const y=e.getContext("2d");if(!y)return;const k=document.createElement("canvas");k.width=u,k.height=h;const d=k.getContext("2d");if(!d)return;d.clearRect(0,0,u,h);const I=await Rt(t,f,u,h);ce(d,I,u,h);const E=await B(n);ce(d,E,u,h);const v=await B(a);ce(d,v,u,h);const S=u/3633;if(Tt(d,p,m,S),o.contactInfo&&(r||l||i)&&Nt(d,r,l,i,o.contactInfo),o.description&&s&&Bt(d,s,o.description),r&&et(d,r,o.namePlate),o.signature){const L=m==="de"?"Unterschrift":"Signature";yn(d,o.signature,L)}e.width=u,e.height=h,y.drawImage(k,0,0)}const Le="money-generator-portrait",Re="money-generator-bg-removed";async function vn(e){try{if(localStorage.removeItem(Le),!e)return;const t=await ft(e);try{localStorage.setItem(Le,t)}catch(n){console.warn("Could not persist portrait to localStorage:",n)}}catch(t){console.warn("Error processing portrait for storage:",t)}}async function kn(e){try{if(localStorage.removeItem(Re),!e)return;const t=await ft(e);try{localStorage.setItem(Re,t)}catch(n){console.warn("Could not persist bg-removed image to localStorage:",n)}}catch(t){console.warn("Error processing bg-removed image for storage:",t)}}function In(){try{return localStorage.getItem(Le)}catch{return null}}function Tn(){try{return localStorage.getItem(Re)}catch{return null}}function En(){try{localStorage.removeItem(Le),localStorage.removeItem(Re)}catch{}}function Sn(){return(typeof navigator<"u"?navigator.language:"de").toLowerCase().startsWith("de")?"de":"en"}const Ce=Sn(),ut={personalInfo:{name:"",email:"",phone:""},voucherConfig:{hours:1,description:"",language:Ce,templateHue:29},portrait:{original:null,enhanced:null,useEnhanced:!1,zoom:1,panX:0,panY:0,rawImage:null,bgRemovedImage:null,bgRemoved:!1,bgOpacity:0,bgBlur:0,engravingIntensity:0},currentSide:"front",isEnhancing:!1,isExporting:!1,appLanguage:Ce},w=tn.create()(nn.persist(e=>({...ut,setPersonalInfo:t=>e(n=>({personalInfo:{...n.personalInfo,...t}})),setVoucherConfig:t=>e(n=>({voucherConfig:{...n.voucherConfig,...t}})),setPortrait:(t,n=null)=>(vn(t),e(a=>({portrait:{...a.portrait,original:t,enhanced:n,useEnhanced:!1,zoom:a.portrait.original&&t?a.portrait.zoom:1,panX:a.portrait.original&&t?a.portrait.panX:0,panY:a.portrait.original&&t?a.portrait.panY:0}}))),setEnhancedPortrait:t=>e(n=>({portrait:{...n.portrait,enhanced:t,useEnhanced:t!==null}})),toggleUseEnhanced:()=>e(t=>({portrait:{...t.portrait,useEnhanced:t.portrait.enhanced?!t.portrait.useEnhanced:!1}})),setPortraitZoom:t=>e(n=>({portrait:{...n.portrait,zoom:t}})),setPortraitPan:(t,n)=>e(a=>({portrait:{...a.portrait,panX:t,panY:n}})),setPortraitRawImage:t=>e(n=>({portrait:{...n.portrait,rawImage:t}})),setPortraitBgRemoved:(t,n)=>(n!==void 0&&kn(n),e(a=>({portrait:{...a.portrait,bgRemoved:t,bgRemovedImage:n!==void 0?n:a.portrait.bgRemovedImage}}))),setPortraitBgOpacity:t=>e(n=>({portrait:{...n.portrait,bgOpacity:t}})),setPortraitBgBlur:t=>e(n=>({portrait:{...n.portrait,bgBlur:t}})),setPortraitEngravingIntensity:t=>e(n=>({portrait:{...n.portrait,engravingIntensity:t}})),setCurrentSide:t=>e({currentSide:t}),flipSide:()=>e(t=>({currentSide:t.currentSide==="front"?"back":"front"})),setIsEnhancing:t=>e({isEnhancing:t}),setIsExporting:t=>e({isExporting:t}),setAppLanguage:t=>e({appLanguage:t}),setBillLanguage:t=>e(n=>({voucherConfig:{...n.voucherConfig,language:t}})),setHours:t=>e(n=>({voucherConfig:{...n.voucherConfig,hours:t}})),setTemplateHue:t=>(Lt(),Pt(),e(n=>({voucherConfig:{...n.voucherConfig,templateHue:t}}))),reset:()=>(En(),e(ut))}),{name:"money-generator-storage",migrate:e=>{const t=e;return t!=null&&t.voucherConfig&&(t.voucherConfig.templateHue===void 0&&(t.voucherConfig.templateHue=29),t.voucherConfig.hours=1,t.voucherConfig.language=Ce),t&&(t.appLanguage=Ce),t},version:2,partialize:e=>({personalInfo:e.personalInfo,voucherConfig:{...e.voucherConfig},appLanguage:e.appLanguage,portrait:{original:null,enhanced:null,useEnhanced:e.portrait.useEnhanced,zoom:e.portrait.zoom,panX:e.portrait.panX,panY:e.portrait.panY,rawImage:null,bgRemovedImage:null,bgRemoved:e.portrait.bgRemoved,bgOpacity:e.portrait.bgOpacity,bgBlur:e.portrait.bgBlur,engravingIntensity:e.portrait.engravingIntensity},currentSide:"front",isEnhancing:!1,isExporting:!1})}));if(typeof window<"u"){const e=In(),t=Tn();e&&setTimeout(()=>{const n=w.getState();if(!n.portrait.original){const a=n.portrait.bgRemoved,r=t!==null;w.setState({portrait:{...n.portrait,original:e,rawImage:e,bgRemovedImage:t,bgRemoved:a&&r,bgOpacity:a&&r?n.portrait.bgOpacity:0,bgBlur:a&&r?n.portrait.bgBlur:0}})}},0)}const Pn={header:{title:"Money Generator",subtitle:"Erstelle deinen persönlichen Zeitgutschein"},form:{personalInfo:{title:"Persönliche Daten",name:"Name",namePlaceholder:"Dein Name",email:"E-Mail",emailPlaceholder:"deine@email.de",phone:"Telefon",phonePlaceholder:"+49 123 456789"},portrait:{title:"Portrait",upload:"Bild hochladen",dragDrop:"oder hierher ziehen",enhance:"Mit AI verbessern",enhancing:"Wird verbessert...",useOriginal:"Original verwenden",useEnhanced:"Verbessertes verwenden",zoom:"Zoom"},voucher:{title:"Gutschein",hours:"Stunden",hourLabel:"Stunde",hoursLabel:"Stunden",description:"Beschreibung",descriptionPlaceholder:"Was kann mit diesem Gutschein eingelöst werden?",billLanguage:"Schein-Sprache",billLanguageGerman:"Deutsch",billLanguageEnglish:"Englisch"},billColor:{title:"Scheinfarbe",label:"Farbton"}},preview:{front:"Vorderseite",back:"Rückseite",flip:"Umdrehen"},export:{button:"Als PDF herunterladen",exporting:"PDF wird erstellt...",success:"Download gestartet!"},bill:{descriptionText:"Für diesen Schein erhältst du {bannerText} meiner Zeit oder ein gleichwertiges Dankeschön.",bannerText:{1:"eine Stunde",5:"fünf Stunden",10:"zehn Stunden"}}},Ln={header:{title:"Money Generator",subtitle:"Create your personal time voucher"},form:{personalInfo:{title:"Personal Information",name:"Name",namePlaceholder:"Your name",email:"Email",emailPlaceholder:"your@email.com",phone:"Phone",phonePlaceholder:"+1 234 567890"},portrait:{title:"Portrait",upload:"Upload image",dragDrop:"or drag and drop",enhance:"Enhance with AI",enhancing:"Enhancing...",useOriginal:"Use original",useEnhanced:"Use enhanced",zoom:"Zoom"},voucher:{title:"Voucher",hours:"Hours",hourLabel:"hour",hoursLabel:"hours",description:"Description",descriptionPlaceholder:"What can be redeemed with this voucher?",billLanguage:"Bill Language",billLanguageGerman:"German",billLanguageEnglish:"English"},billColor:{title:"Bill Color",label:"Hue"}},preview:{front:"Front",back:"Back",flip:"Flip"},export:{button:"Download as PDF",exporting:"Creating PDF...",success:"Download started!"},bill:{descriptionText:"For this voucher, you will receive {bannerText} of my time or an equivalent appreciation in return.",bannerText:{1:"one hour",5:"five hours",10:"ten hours"}}},Rn={de:Pn,en:Ln};function re(e){return Rn[e]}function tt(e,t,n){if(n&&n.trim())return n;const a=re(e),r=a.bill.bannerText[t]||a.bill.bannerText[1];return a.bill.descriptionText.replace("{bannerText}",r)}function Cn(e){return/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e)}function Bn(e){return e.replace(/\D/g,"").length>=6}function Nn({focusField:e,onFocused:t,onFormFocusChange:n}={}){const a=w(d=>d.appLanguage),r=w(d=>d.personalInfo),l=w(d=>d.setPersonalInfo),i=re(a),[s,o]=g.useState(!1),[u,h]=g.useState(!1),f=s&&r.email.trim()&&!Cn(r.email),p=u&&r.phone.trim()&&!Bn(r.phone),m=g.useRef(null),y=g.useRef(null),k=g.useRef(null);return g.useEffect(()=>{if(e){const d=e==="name"?m:e==="email"?y:k;setTimeout(()=>{var I,E;(I=d.current)==null||I.click(),(E=d.current)==null||E.focus(),setTimeout(()=>{var v;(v=d.current)==null||v.scrollIntoView({behavior:"smooth",block:"center"})},300),t==null||t()},100)}},[e,t]),c.jsxs("div",{className:"space-y-4",children:[c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.name})}),c.jsx("input",{ref:m,type:"text",name:"name",autoComplete:"name",placeholder:i.form.personalInfo.namePlaceholder,className:"input input-bordered w-full input-md",value:r.name,onChange:d=>l({name:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>n==null?void 0:n(!1)})]}),c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.email})}),c.jsx("input",{ref:y,type:"email",name:"email",autoComplete:"email",placeholder:i.form.personalInfo.emailPlaceholder,className:`input input-bordered w-full input-md ${f?"input-error":""}`,value:r.email,onChange:d=>l({email:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>{o(!0),n==null||n(!1)}}),f&&c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt text-error",children:a==="de"?"Bitte gib eine gültige E-Mail-Adresse ein":"Please enter a valid email address"})})]}),c.jsxs("div",{className:"form-control",children:[c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text font-medium",children:i.form.personalInfo.phone})}),c.jsx("input",{ref:k,type:"tel",name:"phone",autoComplete:"tel",placeholder:i.form.personalInfo.phonePlaceholder,className:`input input-bordered w-full input-md ${p?"input-error":""}`,value:r.phone,onChange:d=>l({phone:d.target.value}),onFocus:d=>{n==null||n(!0),setTimeout(()=>d.target.scrollIntoView({behavior:"smooth",block:"center"}),300)},onBlur:()=>{h(!0),n==null||n(!1)}}),p&&c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt text-error",children:a==="de"?"Bitte gib eine gültige Telefonnummer ein":"Please enter a valid phone number"})})]})]})}const $e={},jn="https://api.stability.ai/v1/generation",An="https://api.stability.ai/v2beta/stable-image/edit/remove-background",Dt="stability_api_key";let fe=null;function Dn(e){fe=e}function Hn(){return fe}function Mn(){return fe!==null}const Un={vintage:"portrait in the style of vintage currency engraving, fine line work, crosshatching, sepia tones, detailed stippling, classic bank note portrait style",engraved:"portrait as detailed intaglio engraving, currency bill style, fine parallel lines, high contrast, official government portrait",currency:"portrait rendered as US dollar bill engraving, official currency portrait style, green tint, fine line engraving technique"},dt=[{width:1024,height:1024},{width:1152,height:896},{width:1216,height:832},{width:1344,height:768},{width:1536,height:640},{width:640,height:1536},{width:768,height:1344},{width:832,height:1216},{width:896,height:1152}];function On(e,t){const n=e/t;let a=dt[0],r=1/0;for(const l of dt){const i=l.width/l.height,s=Math.abs(n-i);s<r&&(r=s,a=l)}return a}function Yn(e){return new Promise((t,n)=>{const a=new Image;a.onload=()=>{const r=On(a.width,a.height),l=document.createElement("canvas");l.width=r.width,l.height=r.height;const i=l.getContext("2d");if(!i){n(new Error("Failed to get canvas context"));return}const s=a.width/a.height,o=r.width/r.height;let u=0,h=0,f=a.width,p=a.height;s>o?(f=a.height*o,u=(a.width-f)/2):(p=a.width/o,h=(a.height-p)/2),i.drawImage(a,u,h,f,p,0,0,r.width,r.height),t(l.toDataURL("image/png"))},a.onerror=()=>n(new Error("Failed to load image")),a.src=e})}function Ht(e){var i;const t=e.split(","),n=((i=t[0].match(/:(.*?);/))==null?void 0:i[1])||"image/png",a=atob(t[1]),r=a.length,l=new Uint8Array(r);for(let s=0;s<r;s++)l[s]=a.charCodeAt(s);return new Blob([l],{type:n})}function je(){var t;const e=typeof{url:typeof document>"u"?require("url").pathToFileURL(__filename).href:ge&&ge.tagName.toUpperCase()==="SCRIPT"&&ge.src||new URL("index.cjs",document.baseURI).href}<"u"&&($e==null?void 0:$e.VITE_STABILITY_API_KEY)||typeof process<"u"&&((t=process.env)==null?void 0:t.NEXT_PUBLIC_STABILITY_API_KEY);return e&&e!=="your-api-key-here"?e:typeof localStorage<"u"?localStorage.getItem(Dt):null}function Mt(e){localStorage.setItem(Dt,e)}function Pe(){return fe?!0:je()!==null}async function _n(e){const t=je();if(!t)throw new Error("No Stability AI API key configured");const{imageDataUrl:n,style:a,strength:r=.35}=e,l=await Yn(n),i=Ht(l),s=new FormData;s.append("init_image",i,"portrait.png"),s.append("init_image_mode","IMAGE_STRENGTH"),s.append("image_strength",String(1-r)),s.append("text_prompts[0][text]",Un[a]),s.append("text_prompts[0][weight]","1"),s.append("cfg_scale","7"),s.append("samples","1"),s.append("steps","30");const u=await fetch(`${jn}/stable-diffusion-xl-1024-v1-0/image-to-image`,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"application/json"},body:s});if(!u.ok){const f=await u.text();throw console.error("Stability AI error:",f),u.status===401?new Error("Invalid API key"):u.status===402?new Error("Insufficient credits"):u.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${u.status}`)}const h=await u.json();if(!h.artifacts||h.artifacts.length===0)throw new Error("No image generated");return`data:image/png;base64,${h.artifacts[0].base64}`}async function Ut(e){if(fe){const i=await fetch(fe,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({imageDataUrl:e})});if(!i.ok){const o=await i.json().catch(()=>({}));throw new Error(o.error||`API error: ${i.status}`)}return(await i.json()).imageDataUrl}const t=je();if(!t)throw new Error("No Stability AI API key configured");const n=Ht(e),a=new FormData;a.append("image",n,"image.png"),a.append("output_format","png");const r=await fetch(An,{method:"POST",headers:{Authorization:`Bearer ${t}`,Accept:"image/*"},body:a});if(!r.ok){const i=await r.text();throw console.error("Stability AI remove background error:",i),r.status===401?new Error("Invalid API key"):r.status===402?new Error("Insufficient credits"):r.status===429?new Error("Rate limit exceeded. Please try again later."):new Error(`API error: ${r.status}`)}const l=await r.blob();return new Promise((i,s)=>{const o=new FileReader;o.onload=()=>i(o.result),o.onerror=()=>s(new Error("Failed to read result")),o.readAsDataURL(l)})}function Wn(){const[e,t]=g.useState(!1),[n,a]=g.useState(!1),[r,l]=g.useState(null),[i,s]=g.useState(()=>Pe());g.useEffect(()=>{s(Pe());const p=setTimeout(()=>{s(Pe())},150);return()=>clearTimeout(p)},[]);const o=g.useCallback(()=>l(null),[]),u=g.useCallback(p=>{Mt(p),s(!0),l(null)},[]),h=g.useCallback(async(p,m=.5,y=40)=>{t(!0),l(null);try{return await bt(p,m,y)}catch(k){const d=k instanceof Error?k.message:"Enhancement failed";throw l(d),k}finally{t(!1)}},[]),f=g.useCallback(async p=>{a(!0),l(null);try{return await Ut(p)}catch(m){const y=m instanceof Error?m.message:"Background removal failed";throw l(y),m}finally{a(!1)}},[]);return{enhance:h,removeBg:f,isEnhancing:e,isRemovingBg:n,error:r,hasKey:i,setApiKey:u,clearError:o}}function Ot({isOpen:e,onClose:t,onSubmit:n}){const a=w(u=>u.appLanguage),[r,l]=g.useState("");if(!e)return null;const i=u=>{u.preventDefault(),r.trim()&&(n(r.trim()),l(""),t())},o={de:{title:"Stability AI API Key",description:"Um die AI-Bildverbesserung zu nutzen, benötigst du einen Stability AI API Key. Du kannst ihn auf platform.stability.ai erhalten.",placeholder:"sk-...",submit:"Speichern",cancel:"Abbrechen",hint:"Der Key wird lokal in deinem Browser gespeichert."},en:{title:"Stability AI API Key",description:"To use AI image enhancement, you need a Stability AI API key. You can get one at platform.stability.ai.",placeholder:"sk-...",submit:"Save",cancel:"Cancel",hint:"The key is stored locally in your browser."}}[a];return c.jsxs("dialog",{className:"modal modal-open",children:[c.jsxs("div",{className:"modal-box",children:[c.jsx("h3",{className:"font-bold text-lg",children:o.title}),c.jsx("p",{className:"py-4 text-sm opacity-80",children:o.description}),c.jsxs("form",{onSubmit:i,children:[c.jsxs("div",{className:"form-control",children:[c.jsx("input",{type:"password",placeholder:o.placeholder,className:"input input-bordered w-full",value:r,onChange:u=>l(u.target.value),autoFocus:!0}),c.jsx("label",{className:"label",children:c.jsx("span",{className:"label-text-alt",children:o.hint})})]}),c.jsxs("div",{className:"modal-action",children:[c.jsx("button",{type:"button",className:"btn btn-ghost",onClick:t,children:o.cancel}),c.jsx("button",{type:"submit",className:"btn btn-primary",disabled:!r.trim(),children:o.submit})]})]})]}),c.jsx("form",{method:"dialog",className:"modal-backdrop",children:c.jsx("button",{onClick:t,children:"close"})})]})}function ye({min:e,max:t,step:n,value:a,onChange:r,className:l="",disabled:i=!1}){const s=g.useRef(null),o=g.useRef(null),u=g.useRef(!1),[h,f]=g.useState(!1),p=(a-e)/(t-e)*100,m=g.useCallback(v=>{if(!s.current)return a;const S=s.current.getBoundingClientRect(),L=Math.max(0,Math.min(1,(v-S.left)/S.width)),P=t-e,D=e+L*P,j=Math.round(D/n)*n;return Math.max(e,Math.min(t,j))},[e,t,n,a]),y=g.useCallback(v=>{if(i)return;const S=v.touches[0];o.current={x:S.clientX,y:S.clientY,value:a,decided:!1},u.current=!1},[a,i]),k=g.useCallback(v=>{if(i||!o.current)return;const S=v.touches[0],L=Math.abs(S.clientX-o.current.x),P=Math.abs(S.clientY-o.current.y);if(!o.current.decided){if(L<8&&P<8)return;if(o.current.decided=!0,P>L){o.current=null;return}u.current=!0,f(!0)}if(u.current){const D=m(S.clientX);D!==a&&r(D)}},[i,m,r,a]),d=g.useCallback(v=>{if(o.current&&!o.current.decided){const S=v.changedTouches[0];if(S){const L=m(S.clientX);L!==a&&r(L)}}o.current=null,u.current=!1,f(!1)},[m,r,a]);g.useEffect(()=>{const v=s.current;if(!v)return;const S=L=>{u.current&&L.preventDefault()};return v.addEventListener("touchmove",S,{passive:!1}),()=>{v.removeEventListener("touchmove",S)}},[]);const I=g.useCallback(v=>{if(i)return;const S=m(v.clientX);r(S),f(!0);const L=D=>{const j=m(D.clientX);r(j)},P=()=>{f(!1),document.removeEventListener("mousemove",L),document.removeEventListener("mouseup",P)};document.addEventListener("mousemove",L),document.addEventListener("mouseup",P)},[i,m,r]),E=`calc(10px + (100% - 20px) * ${p/100})`;return c.jsxs("div",{ref:s,className:`relative h-10 flex items-center cursor-pointer overflow-visible ${i?"opacity-50 cursor-not-allowed":""}`,onTouchStart:y,onTouchMove:k,onTouchEnd:d,onMouseDown:I,children:[c.jsx("div",{className:"absolute h-2 bg-base-300 rounded-full inset-x-0"}),c.jsx("div",{className:`absolute h-2 rounded-full transition-colors ${l.includes("range-primary")?"bg-primary":l.includes("range-secondary")?"bg-secondary":"bg-primary"}`,style:{left:0,width:E}}),c.jsx("div",{className:`absolute w-5 h-5 rounded-full bg-base-100 border-2 shadow-md transition-transform ${h?"scale-110":""} ${l.includes("range-primary")?"border-primary":l.includes("range-secondary")?"border-secondary":"border-primary"}`,style:{left:E,transform:"translateX(-50%)"}})]})}function zn(){const e=w(b=>b.appLanguage),t=w(b=>b.portrait),n=w(b=>b.setPortrait),a=w(b=>b.setPortraitZoom),r=w(b=>b.setPortraitPan),l=w(b=>b.setPortraitRawImage),i=w(b=>b.setPortraitBgRemoved),s=w(b=>b.setPortraitBgOpacity),o=w(b=>b.setPortraitBgBlur),u=w(b=>b.setPortraitEngravingIntensity),{enhance:h,removeBg:f,isEnhancing:p,isRemovingBg:m,error:y,hasKey:k,setApiKey:d}=Wn(),I=re(e),E=g.useRef(null),[v,S]=g.useState(!1),[L,P]=g.useState(!1),D=g.useRef(null),j=g.useRef(null),R=t.rawImage,C=t.bgRemovedImage,Y=t.bgRemoved,q=t.bgOpacity,H=t.bgBlur,O=t.engravingIntensity;g.useEffect(()=>{t.original&&!t.rawImage&&l(t.original)},[t.original,t.rawImage,l]),g.useEffect(()=>()=>{D.current&&clearTimeout(D.current),j.current&&clearTimeout(j.current)},[]);const Z=w(b=>b.voucherConfig.templateHue),oe=g.useRef(Z),J=g.useCallback(async b=>{if(!b.type.startsWith("image/"))return;const T=new FileReader;T.onload=async M=>{var _;const A=(_=M.target)==null?void 0:_.result,V=await pt(A);on(),l(V),n(V),a(1),r(0,0),i(!1,null),s(0),o(0),u(0)},T.readAsDataURL(b)},[n,l,a,r,i,s,o,u]),be=g.useCallback(b=>{b.preventDefault(),S(!1);const T=b.dataTransfer.files[0];T&&J(T)},[J]),G=g.useCallback(b=>{b.preventDefault(),S(!0)},[]),Q=g.useCallback(b=>{b.preventDefault(),S(!1)},[]),K=()=>{var b;(b=E.current)==null||b.click()},xe=b=>{var M;const T=(M=b.target.files)==null?void 0:M[0];T&&J(T)},ee=g.useCallback(async(b,T,M)=>{try{return await h(b,T,M)}catch(A){return console.error("Enhancement failed:",A),b}},[h]),ve=g.useCallback(async b=>{try{const T=await f(b);return i(!0,T),T}catch(T){return console.error("Background removal failed:",T),b}},[f,i]),te=g.useCallback(async()=>{const b=w.getState(),T=b.portrait,M=b.voucherConfig.templateHue;if(!T.rawImage)return;let A;T.bgRemoved&&T.bgRemovedImage?A=await ze(T.bgRemovedImage,T.rawImage,T.bgOpacity,T.bgBlur):A=T.rawImage,T.engravingIntensity>0&&(A=await ee(A,T.engravingIntensity,M)),n(A)},[ee,n]);g.useEffect(()=>{if(oe.current===Z)return;oe.current=Z;const b=w.getState().portrait;b.engravingIntensity>0&&b.rawImage&&(D.current&&clearTimeout(D.current),D.current=setTimeout(te,150))},[Z,te]);const He=async()=>{if(!R)return;if(!Y&&!k){P(!0);return}if(!Y){const T=await ve(R),M=w.getState(),A=M.portrait,V=M.voucherConfig.templateHue;let _=await ze(T,R,A.bgOpacity,A.bgBlur);A.engravingIntensity>0&&(_=await ee(_,A.engravingIntensity,V)),n(_)}else{i(!1,null);const T=w.getState(),M=T.portrait.engravingIntensity,A=T.voucherConfig.templateHue;if(M>0){const V=await ee(R,M,A);n(V)}else n(R)}},we=b=>{u(b),D.current&&clearTimeout(D.current),R&&(D.current=setTimeout(te,150))},Me=async b=>{if(d(b),!R)return;const T=await ve(R),M=w.getState(),A=M.portrait,V=M.voucherConfig.templateHue;let _=await ze(T,R,A.bgOpacity,A.bgBlur);A.engravingIntensity>0&&(_=await ee(_,A.engravingIntensity,V)),n(_)},ke=b=>{s(b),j.current&&clearTimeout(j.current),!(!R||!C)&&(j.current=setTimeout(te,150))},Ie=b=>{o(b),j.current&&clearTimeout(j.current),!(!R||!C)&&(j.current=setTimeout(te,150))};return c.jsxs("div",{className:"space-y-4",children:[c.jsx("style",{children:`
|
|
2
2
|
@keyframes sparkle1 {
|
|
3
3
|
0%, 33%, 100% { opacity: 0.3; }
|
|
4
4
|
16% { opacity: 1; }
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
0%, 66%, 100% { opacity: 0.3; }
|
|
12
12
|
83% { opacity: 1; }
|
|
13
13
|
}
|
|
14
|
-
`}),t.original?c.jsxs("div",{className:"flex flex-col space-y-4",children:[c.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:I.form.portrait.zoom}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),c.jsx(ye,{min:.5,max:2,step:.05,value:t.zoom,onChange:a,className:"range range-primary range-sm"})]}),c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",p&&c.jsx("span",{className:"loading loading-spinner loading-xs"})]}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(O*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:O,onChange:we,className:"range range-secondary range-sm",disabled:p||!R})]})]}),Y?c.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(q*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:q,onChange:ke,className:"range range-primary range-sm"})]}),c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(H*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:H,onChange:Ie,className:"range range-primary range-sm",disabled:q===0})]})]}):c.jsx("div",{className:"flex justify-center",children:c.jsxs("button",{className:"btn btn-ghost btn gap-2 text-base-content/70",onClick:De,disabled:m||!R,children:[c.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:[c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z",style:m?{animation:"sparkle1 2.4s ease-in-out infinite"}:void 0}),c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z",style:m?{animation:"sparkle2 2.4s ease-in-out infinite"}:void 0}),c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z",style:m?{animation:"sparkle3 2.4s ease-in-out infinite"}:void 0})]}),m?e==="de"?"Hintergrund wird entfernt ...":"Removing background ...":e==="de"?"Hintergrund entfernen":"Remove background",!m&&!k&&c.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})}),y&&c.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),c.jsx("span",{children:y})]})]}):c.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${m?"border-primary bg-primary/10 pointer-events-none":v?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:be,onDragOver:G,onDragLeave:Q,onClick:K,children:[c.jsx("input",{ref:E,type:"file",accept:"image/*",className:"hidden",onChange:xe}),m?c.jsxs("div",{className:"flex flex-col items-center gap-2",children:[c.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),c.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt ...":"Removing background ..."})]}):c.jsxs("div",{className:"flex flex-col items-center gap-2",children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),c.jsx("p",{className:"font-medium",children:I.form.portrait.upload}),c.jsx("p",{className:"text-sm text-base-content/60",children:I.form.portrait.dragDrop})]})]}),c.jsx(Ut,{isOpen:L,onClose:()=>P(!1),onSubmit:He})]})}function $n(){const e=w(s=>s.appLanguage),t=w(s=>s.voucherConfig.language),n=w(s=>s.voucherConfig.hours);w(s=>s.voucherConfig.templateHue);const a=w(s=>s.setBillLanguage),r=w(s=>s.setHours);w(s=>s.setTemplateHue);const l=re(e),i=[1,5,10];return c.jsxs("div",{className:"space-y-4",children:[c.jsx("div",{className:"form-control",children:c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("span",{className:"label-text font-medium",children:l.form.voucher.billLanguage}),c.jsxs("div",{className:"join border border-base-300 rounded-lg shadow",children:[c.jsx("button",{className:`join-item btn btn-md ${t==="de"?"btn-primary":"btn-ghost"}`,onClick:()=>a("de"),children:l.form.voucher.billLanguageGerman}),c.jsx("button",{className:`join-item btn btn-md ${t==="en"?"btn-primary":"btn-ghost"}`,onClick:()=>a("en"),children:l.form.voucher.billLanguageEnglish})]})]})}),c.jsx("div",{className:"form-control",children:c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("span",{className:"label-text font-medium",children:l.form.voucher.hours}),c.jsx("div",{className:"join border border-base-300 rounded-lg shadow",children:i.map(s=>c.jsxs("button",{className:`join-item btn btn-md ${n===s?"btn-primary":"btn-ghost"}`,onClick:()=>r(s),children:[s,c.jsxs("span",{className:"hidden sm:inline",children:[" ",s===1?l.form.voucher.hourLabel:l.form.voucher.hoursLabel]})]},s))})]})}),!1]})}function nt(e,t){return{front:"",back:"",width:ne,height:ae}}const je={front:{portrait:{x:1810,y:918,radiusX:570,radiusY:605},namePlate:{x:1816,y:1765,fontSize:85,maxWidth:898,align:"center"}},back:{portrait:{x:0,y:0,radiusX:0,radiusY:0},namePlate:{x:1816,y:1770,fontSize:85,maxWidth:898,align:"center"},contactInfo:{x:898,y:939,fontSize:93,lineHeight:165,align:"center"},description:{x:2721,y:939,fontSize:85,maxWidth:1177,lineHeight:124,align:"center"},signature:{x:1820,y:1445,width:950,height:145,labelFontSize:85}}},ue=je,de=je;function at(e){return je}const Je=.75;function Xn(e){const t=at(),n=Je,a=r=>({portrait:{x:r.portrait.x*n,y:r.portrait.y*n,radiusX:r.portrait.radiusX*n,radiusY:r.portrait.radiusY*n},namePlate:{x:r.namePlate.x*n,y:r.namePlate.y*n,fontSize:r.namePlate.fontSize*n,maxWidth:r.namePlate.maxWidth?r.namePlate.maxWidth*n:void 0,lineHeight:r.namePlate.lineHeight?r.namePlate.lineHeight*n:void 0,align:r.namePlate.align},contactInfo:r.contactInfo?{x:r.contactInfo.x*n,y:r.contactInfo.y*n,fontSize:r.contactInfo.fontSize*n,maxWidth:r.contactInfo.maxWidth?r.contactInfo.maxWidth*n:void 0,lineHeight:r.contactInfo.lineHeight?r.contactInfo.lineHeight*n:void 0,align:r.contactInfo.align}:void 0,description:r.description?{x:r.description.x*n,y:r.description.y*n,fontSize:r.description.fontSize*n,maxWidth:r.description.maxWidth?r.description.maxWidth*n:void 0,lineHeight:r.description.lineHeight?r.description.lineHeight*n:void 0,align:r.description.align}:void 0,signature:r.signature?{x:r.signature.x*n,y:r.signature.y*n,width:r.signature.width*n,height:r.signature.height*n,labelFontSize:r.signature.labelFontSize*n}:void 0});return{front:a(t.front),back:a(t.back)}}function Gn(e,t){const n=nt();return{...n,width:Math.round(n.width*Je),height:Math.round(n.height*Je)}}function Vn(e,t){const[n,a]=g.useState(e);return g.useEffect(()=>{const r=setTimeout(()=>a(e),t);return()=>clearTimeout(r)},[e,t]),n}function Kn({onPortraitClick:e,onFileDrop:t}={}){const n=w(x=>x.appLanguage),a=w(x=>x.voucherConfig.language),r=w(x=>x.voucherConfig.hours),l=w(x=>x.voucherConfig.description),i=w(x=>x.voucherConfig.templateHue),s=w(x=>x.personalInfo),o=w(x=>x.portrait),u=w(x=>x.currentSide),h=w(x=>x.flipSide),f=w(x=>x.setPortraitPan),p=Vn(i,150),m=re(n),y=g.useRef(null),k=g.useRef(null),d=g.useRef(null),[I,E]=g.useState(!1),[v,S]=g.useState(!1),[L,P]=g.useState(!1),[D,j]=g.useState(!1),R=g.useRef(null),C=g.useRef(null),Y=g.useRef(!1),q=g.useRef(0),H=Gn(),O=Xn(),Z=o.useEnhanced&&o.enhanced?o.enhanced:o.original,oe=tt(a,r,l),[J,be]=g.useState(""),[G,Q]=g.useState(""),[K,xe]=g.useState(""),[ee,ve]=g.useState(""),[te,De]=g.useState(""),[we,He]=g.useState(""),[ke,Ie]=g.useState(!0);g.useEffect(()=>{let x=!0;Ie(!0);async function N(){const[U,z]=await Promise.all([Ze(r,a,"front"),Ze(r,a,"back")]);x&&(be(U.background),Q(U.badges),xe(U.frame),ve(z.background),De(z.badges),He(z.frame),Ie(!1))}return N(),()=>{x=!1}},[r,a]),g.useEffect(()=>{!y.current||!J||!G||!K||Nt(y.current,J,G,K,Z,s.name,O.front,H.width,H.height,o.zoom,o.panX,o.panY,p,r,a)},[H,J,G,K,Z,s.name,O,o.zoom,o.panX,o.panY,p,r,a]),g.useEffect(()=>{!k.current||!ee||!te||!we||jt(k.current,ee,te,we,s.name,s.email,s.phone,oe,O.back,H.width,H.height,p,r,a)},[H,ee,te,we,s,oe,O,p,r,a]);const b=()=>{E(!I),h()};g.useEffect(()=>{E(u==="back")},[u]);const T=g.useCallback((x,N)=>{if(!d.current||u!=="front")return!1;const U=d.current.getBoundingClientRect(),z=U.width/H.width,Me=U.height/H.height,Te=(x-U.left)/z,Ue=(N-U.top)/Me,{x:Oe,y:Ye,radiusX:_e,radiusY:Qt}=O.front.portrait,it=(Te-Oe)/_e,st=(Ue-Ye)/Qt;return it*it+st*st<=1},[u,H.width,H.height,O.front.portrait]),M=5,A=g.useCallback((x,N)=>{o.original&&(S(!0),R.current={x,y:N,panX:o.panX,panY:o.panY})},[o.original,o.panX,o.panY]),V=g.useCallback((x,N)=>{if(!v||!R.current||!d.current)return;const U=performance.now();if(U-q.current<33)return;q.current=U;const z=d.current.getBoundingClientRect(),Te=4/Math.max(z.width,z.height)*o.zoom,Ue=(x-R.current.x)*Te,Oe=(N-R.current.y)*Te,Ye=Math.max(-1,Math.min(1,R.current.panX+Ue)),_e=Math.max(-1,Math.min(1,R.current.panY+Oe));f(Ye,_e)},[v,f,o.zoom]),_=g.useCallback(()=>{S(!1),R.current=null,C.current=null},[]),rt=g.useCallback(()=>{e&&e()},[e]),$t=x=>{T(x.clientX,x.clientY)&&(x.preventDefault(),C.current={x:x.clientX,y:x.clientY},Y.current=!1)},Xt=x=>{if(P(T(x.clientX,x.clientY)),C.current&&o.original){const N=x.clientX-C.current.x,U=x.clientY-C.current.y;Math.sqrt(N*N+U*U)>M&&!v&&(Y.current=!0,A(C.current.x,C.current.y))}v&&V(x.clientX,x.clientY)},Gt=x=>{C.current&&!Y.current&&T(x.clientX,x.clientY)&&rt(),_()},Vt=()=>{_(),P(!1)},Kt=x=>{if(x.touches.length===1){const N=x.touches[0];T(N.clientX,N.clientY)&&(C.current={x:N.clientX,y:N.clientY},Y.current=!1)}},Ft=x=>{if(x.touches.length===1&&C.current&&o.original){const N=x.touches[0],U=N.clientX-C.current.x,z=N.clientY-C.current.y;Math.sqrt(U*U+z*z)>M&&!v&&(Y.current=!0,A(C.current.x,C.current.y)),v&&V(N.clientX,N.clientY)}},qt=()=>{C.current&&!Y.current&&T(C.current.x,C.current.y)&&rt(),_()},ot=g.useRef(!1);g.useEffect(()=>{ot.current=v},[v]),g.useEffect(()=>{const x=d.current;if(!x)return;const N=U=>{ot.current&&U.preventDefault()};return x.addEventListener("touchmove",N,{passive:!1}),()=>{x.removeEventListener("touchmove",N)}},[]);const Zt=u==="front"&&o.original,Jt=H.width/H.height;return c.jsxs("div",{className:"space-y-2",children:[c.jsxs("div",{className:"flex justify-between items-center mb-6",children:[c.jsxs("div",{className:"join border border-base-300 rounded-lg",children:[c.jsx("button",{className:`join-item btn btn-md ${u==="front"?"btn-primary":"btn-ghost"}`,onClick:()=>u!=="front"&&b(),children:m.preview.front}),c.jsx("button",{className:`join-item btn btn-md ${u==="back"?"btn-primary":"btn-ghost"}`,onClick:()=>u!=="back"&&b(),children:m.preview.back})]}),c.jsxs("button",{className:"btn btn-ghost btn-md",onClick:b,children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),c.jsx("span",{className:"hidden sm:inline",children:m.preview.flip})]})]}),c.jsxs("div",{className:"relative w-full overflow-visible",style:{aspectRatio:Jt,perspective:"1500px"},children:[ke&&c.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-base-300 rounded-lg z-10",children:c.jsx("span",{className:"loading loading-spinner loading-lg text-primary"})}),c.jsxs("div",{ref:d,className:`relative w-full h-full shadow-lg ${L&&Zt?v?"cursor-grabbing":"cursor-grab":""} ${ke?"opacity-0":"opacity-100"} transition-opacity duration-300`,style:{transformStyle:"preserve-3d",transition:"transform 0.6s ease-in-out, opacity 0.3s ease-in-out",transform:I?"rotateY(180deg)":"rotateY(0deg)"},onMouseDown:$t,onMouseMove:Xt,onMouseUp:Gt,onMouseLeave:Vt,onTouchStart:Kt,onTouchMove:Ft,onTouchEnd:qt,onDragOver:x=>{x.preventDefault(),u==="front"&&j(!0)},onDragLeave:x=>{x.preventDefault(),j(!1)},onDrop:x=>{if(x.preventDefault(),j(!1),u==="front"&&t){const N=x.dataTransfer.files[0];N&&N.type.startsWith("image/")&&t(N)}},children:[c.jsx("canvas",{ref:y,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"}}),c.jsx("canvas",{ref:k,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden",transform:"rotateY(180deg)"}}),u==="front"&&!o.original&&c.jsx("div",{className:`absolute flex flex-col items-center justify-center transition-colors duration-300 ease-in-out pointer-events-none ${D?"bg-primary/20":"hover:bg-base-content/5"}`,style:{left:`${(O.front.portrait.x-O.front.portrait.radiusX)/H.width*100}%`,top:`${(O.front.portrait.y-O.front.portrait.radiusY)/H.height*100}%`,width:`${O.front.portrait.radiusX*2/H.width*100}%`,height:`${O.front.portrait.radiusY*2/H.height*100}%`,borderRadius:"50%",backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"},children:c.jsxs("button",{className:"btn btn-dash hover:btn-dash hover:border-base-content/60 flex flex-col items-center gap-0.5 sm:gap-1 h-auto py-1.5 px-2.5 sm:py-3 sm:px-4 bg-base-100/20 hover:bg-base-100/30",children:[c.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",className:"w-7 h-6 sm:w-10 sm:h-9 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("circle",{cx:"12",cy:"8",r:"4"}),c.jsx("path",{d:"M4 21c0-4 4-6 8-6s8 2 8 6"})]}),c.jsx("span",{className:"text-[10px] sm:text-xs text-center leading-tight whitespace-pre-line",children:n==="de"?`Foto
|
|
14
|
+
`}),t.original?c.jsxs("div",{className:"flex flex-col space-y-4",children:[c.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:I.form.portrait.zoom}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(t.zoom*100),"%"]})]}),c.jsx(ye,{min:.5,max:2,step:.05,value:t.zoom,onChange:a,className:"range range-primary range-sm"})]}),c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsxs("span",{className:"label-text flex items-center gap-2",children:[e==="de"?"Farbanpassung":"Color adjustment",p&&c.jsx("span",{className:"loading loading-spinner loading-xs"})]}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(O*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:O,onChange:we,className:"range range-secondary range-sm",disabled:p||!R})]})]}),Y?c.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-4 w-full",children:[c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:e==="de"?"Hintergrund":"Background"}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(q*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:q,onChange:ke,className:"range range-primary range-sm"})]}),c.jsxs("div",{className:"form-control w-full",children:[c.jsxs("label",{className:"label",children:[c.jsx("span",{className:"label-text",children:e==="de"?"Unschärfe":"Blur"}),c.jsxs("span",{className:"label-text-alt",children:[Math.round(H*100),"%"]})]}),c.jsx(ye,{min:0,max:1,step:.05,value:H,onChange:Ie,className:"range range-primary range-sm",disabled:q===0})]})]}):c.jsx("div",{className:"flex justify-center",children:c.jsxs("button",{className:"btn btn-ghost btn gap-2 text-base-content/70",onClick:He,disabled:m||!R,children:[c.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:[c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z",style:m?{animation:"sparkle1 2.4s ease-in-out infinite"}:void 0}),c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456z",style:m?{animation:"sparkle2 2.4s ease-in-out infinite"}:void 0}),c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z",style:m?{animation:"sparkle3 2.4s ease-in-out infinite"}:void 0})]}),m?e==="de"?"Hintergrund wird entfernt ...":"Removing background ...":e==="de"?"Hintergrund entfernen":"Remove background",!m&&!k&&c.jsx("span",{className:"badge badge-sm badge-outline",children:"API"})]})}),y&&c.jsxs("div",{className:"alert alert-warning text-sm py-2",children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"stroke-current shrink-0 h-5 w-5",fill:"none",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:"2",d:"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"})}),c.jsx("span",{children:y})]})]}):c.jsxs("div",{className:`border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-colors ${m?"border-primary bg-primary/10 pointer-events-none":v?"border-primary bg-primary/10":"border-base-300 hover:border-primary hover:bg-base-200"}`,onDrop:be,onDragOver:G,onDragLeave:Q,onClick:K,children:[c.jsx("input",{ref:E,type:"file",accept:"image/*",className:"hidden",onChange:xe}),m?c.jsxs("div",{className:"flex flex-col items-center gap-2",children:[c.jsx("span",{className:"loading loading-spinner loading-lg text-primary"}),c.jsx("p",{className:"font-medium",children:e==="de"?"Hintergrund wird entfernt ...":"Removing background ..."})]}):c.jsxs("div",{className:"flex flex-col items-center gap-2",children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-12 w-12 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"})}),c.jsx("p",{className:"font-medium",children:I.form.portrait.upload}),c.jsx("p",{className:"text-sm text-base-content/60",children:I.form.portrait.dragDrop})]})]}),c.jsx(Ot,{isOpen:L,onClose:()=>P(!1),onSubmit:Me})]})}function $n(){const e=w(s=>s.appLanguage),t=w(s=>s.voucherConfig.language),n=w(s=>s.voucherConfig.hours);w(s=>s.voucherConfig.templateHue);const a=w(s=>s.setBillLanguage),r=w(s=>s.setHours);w(s=>s.setTemplateHue);const l=re(e),i=[1,5,10];return c.jsxs("div",{className:"space-y-4",children:[c.jsx("div",{className:"form-control",children:c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("span",{className:"label-text font-medium",children:l.form.voucher.billLanguage}),c.jsxs("div",{className:"join border border-base-300 rounded-lg shadow",children:[c.jsx("button",{className:`join-item btn btn-md ${t==="de"?"btn-primary":"btn-ghost"}`,onClick:()=>a("de"),children:l.form.voucher.billLanguageGerman}),c.jsx("button",{className:`join-item btn btn-md ${t==="en"?"btn-primary":"btn-ghost"}`,onClick:()=>a("en"),children:l.form.voucher.billLanguageEnglish})]})]})}),c.jsx("div",{className:"form-control",children:c.jsxs("div",{className:"flex items-center justify-between gap-2",children:[c.jsx("span",{className:"label-text font-medium",children:l.form.voucher.hours}),c.jsx("div",{className:"join border border-base-300 rounded-lg shadow",children:i.map(s=>c.jsxs("button",{className:`join-item btn btn-md ${n===s?"btn-primary":"btn-ghost"}`,onClick:()=>r(s),children:[s,c.jsxs("span",{className:"hidden sm:inline",children:[" ",s===1?l.form.voucher.hourLabel:l.form.voucher.hoursLabel]})]},s))})]})}),!1]})}function nt(e,t){return{front:"",back:"",width:ne,height:ae}}const Ae={front:{portrait:{x:1810,y:918,radiusX:570,radiusY:605},namePlate:{x:1816,y:1765,fontSize:85,maxWidth:898,align:"center"}},back:{portrait:{x:0,y:0,radiusX:0,radiusY:0},namePlate:{x:1816,y:1770,fontSize:85,maxWidth:898,align:"center"},contactInfo:{x:898,y:939,fontSize:93,lineHeight:165,align:"center"},description:{x:2721,y:939,fontSize:85,maxWidth:1177,lineHeight:124,align:"center"},signature:{x:1820,y:1445,width:950,height:145,labelFontSize:85}}},ue=Ae,de=Ae;function at(e){return Ae}const Je=.75;function Xn(e){const t=at(),n=Je,a=r=>({portrait:{x:r.portrait.x*n,y:r.portrait.y*n,radiusX:r.portrait.radiusX*n,radiusY:r.portrait.radiusY*n},namePlate:{x:r.namePlate.x*n,y:r.namePlate.y*n,fontSize:r.namePlate.fontSize*n,maxWidth:r.namePlate.maxWidth?r.namePlate.maxWidth*n:void 0,lineHeight:r.namePlate.lineHeight?r.namePlate.lineHeight*n:void 0,align:r.namePlate.align},contactInfo:r.contactInfo?{x:r.contactInfo.x*n,y:r.contactInfo.y*n,fontSize:r.contactInfo.fontSize*n,maxWidth:r.contactInfo.maxWidth?r.contactInfo.maxWidth*n:void 0,lineHeight:r.contactInfo.lineHeight?r.contactInfo.lineHeight*n:void 0,align:r.contactInfo.align}:void 0,description:r.description?{x:r.description.x*n,y:r.description.y*n,fontSize:r.description.fontSize*n,maxWidth:r.description.maxWidth?r.description.maxWidth*n:void 0,lineHeight:r.description.lineHeight?r.description.lineHeight*n:void 0,align:r.description.align}:void 0,signature:r.signature?{x:r.signature.x*n,y:r.signature.y*n,width:r.signature.width*n,height:r.signature.height*n,labelFontSize:r.signature.labelFontSize*n}:void 0});return{front:a(t.front),back:a(t.back)}}function Gn(e,t){const n=nt();return{...n,width:Math.round(n.width*Je),height:Math.round(n.height*Je)}}function Vn(e,t){const[n,a]=g.useState(e);return g.useEffect(()=>{const r=setTimeout(()=>a(e),t);return()=>clearTimeout(r)},[e,t]),n}function Kn({onPortraitClick:e,onFileDrop:t}={}){const n=w(x=>x.appLanguage),a=w(x=>x.voucherConfig.language),r=w(x=>x.voucherConfig.hours),l=w(x=>x.voucherConfig.description),i=w(x=>x.voucherConfig.templateHue),s=w(x=>x.personalInfo),o=w(x=>x.portrait),u=w(x=>x.currentSide),h=w(x=>x.flipSide),f=w(x=>x.setPortraitPan),p=Vn(i,150),m=re(n),y=g.useRef(null),k=g.useRef(null),d=g.useRef(null),[I,E]=g.useState(!1),[v,S]=g.useState(!1),[L,P]=g.useState(!1),[D,j]=g.useState(!1),R=g.useRef(null),C=g.useRef(null),Y=g.useRef(!1),q=g.useRef(0),H=Gn(),O=Xn(),Z=o.useEnhanced&&o.enhanced?o.enhanced:o.original,oe=tt(a,r,l),[J,be]=g.useState(""),[G,Q]=g.useState(""),[K,xe]=g.useState(""),[ee,ve]=g.useState(""),[te,He]=g.useState(""),[we,Me]=g.useState(""),[ke,Ie]=g.useState(!0);g.useEffect(()=>{let x=!0;Ie(!0);async function N(){const[U,z]=await Promise.all([Ze(r,a,"front"),Ze(r,a,"back")]);x&&(be(U.background),Q(U.badges),xe(U.frame),ve(z.background),He(z.badges),Me(z.frame),Ie(!1))}return N(),()=>{x=!1}},[r,a]),g.useEffect(()=>{!y.current||!J||!G||!K||jt(y.current,J,G,K,Z,s.name,O.front,H.width,H.height,o.zoom,o.panX,o.panY,p,r,a)},[H,J,G,K,Z,s.name,O,o.zoom,o.panX,o.panY,p,r,a]),g.useEffect(()=>{!k.current||!ee||!te||!we||At(k.current,ee,te,we,s.name,s.email,s.phone,oe,O.back,H.width,H.height,p,r,a)},[H,ee,te,we,s,oe,O,p,r,a]);const b=()=>{E(!I),h()};g.useEffect(()=>{E(u==="back")},[u]);const T=g.useCallback((x,N)=>{if(!d.current||u!=="front")return!1;const U=d.current.getBoundingClientRect(),z=U.width/H.width,Ue=U.height/H.height,Te=(x-U.left)/z,Oe=(N-U.top)/Ue,{x:Ye,y:_e,radiusX:We,radiusY:en}=O.front.portrait,it=(Te-Ye)/We,st=(Oe-_e)/en;return it*it+st*st<=1},[u,H.width,H.height,O.front.portrait]),M=5,A=g.useCallback((x,N)=>{o.original&&(S(!0),R.current={x,y:N,panX:o.panX,panY:o.panY})},[o.original,o.panX,o.panY]),V=g.useCallback((x,N)=>{if(!v||!R.current||!d.current)return;const U=performance.now();if(U-q.current<33)return;q.current=U;const z=d.current.getBoundingClientRect(),Te=4/Math.max(z.width,z.height)*o.zoom,Oe=(x-R.current.x)*Te,Ye=(N-R.current.y)*Te,_e=Math.max(-1,Math.min(1,R.current.panX+Oe)),We=Math.max(-1,Math.min(1,R.current.panY+Ye));f(_e,We)},[v,f,o.zoom]),_=g.useCallback(()=>{S(!1),R.current=null,C.current=null},[]),rt=g.useCallback(()=>{e&&e()},[e]),Xt=x=>{T(x.clientX,x.clientY)&&(x.preventDefault(),C.current={x:x.clientX,y:x.clientY},Y.current=!1)},Gt=x=>{if(P(T(x.clientX,x.clientY)),C.current&&o.original){const N=x.clientX-C.current.x,U=x.clientY-C.current.y;Math.sqrt(N*N+U*U)>M&&!v&&(Y.current=!0,A(C.current.x,C.current.y))}v&&V(x.clientX,x.clientY)},Vt=x=>{C.current&&!Y.current&&T(x.clientX,x.clientY)&&rt(),_()},Kt=()=>{_(),P(!1)},Ft=x=>{if(x.touches.length===1){const N=x.touches[0];T(N.clientX,N.clientY)&&(C.current={x:N.clientX,y:N.clientY},Y.current=!1)}},qt=x=>{if(x.touches.length===1&&C.current&&o.original){const N=x.touches[0],U=N.clientX-C.current.x,z=N.clientY-C.current.y;Math.sqrt(U*U+z*z)>M&&!v&&(Y.current=!0,A(C.current.x,C.current.y)),v&&V(N.clientX,N.clientY)}},Zt=()=>{C.current&&!Y.current&&T(C.current.x,C.current.y)&&rt(),_()},ot=g.useRef(!1);g.useEffect(()=>{ot.current=v},[v]),g.useEffect(()=>{const x=d.current;if(!x)return;const N=U=>{ot.current&&U.preventDefault()};return x.addEventListener("touchmove",N,{passive:!1}),()=>{x.removeEventListener("touchmove",N)}},[]);const Jt=u==="front"&&o.original,Qt=H.width/H.height;return c.jsxs("div",{className:"space-y-2",children:[c.jsxs("div",{className:"flex justify-between items-center mb-6",children:[c.jsxs("div",{className:"join border border-base-300 rounded-lg",children:[c.jsx("button",{className:`join-item btn btn-md ${u==="front"?"btn-primary":"btn-ghost"}`,onClick:()=>u!=="front"&&b(),children:m.preview.front}),c.jsx("button",{className:`join-item btn btn-md ${u==="back"?"btn-primary":"btn-ghost"}`,onClick:()=>u!=="back"&&b(),children:m.preview.back})]}),c.jsxs("button",{className:"btn btn-ghost btn-md",onClick:b,children:[c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"})}),c.jsx("span",{className:"hidden sm:inline",children:m.preview.flip})]})]}),c.jsxs("div",{className:"relative w-full overflow-visible",style:{aspectRatio:Qt,perspective:"1500px"},children:[ke&&c.jsx("div",{className:"absolute inset-0 flex items-center justify-center bg-base-300 rounded-lg z-10",children:c.jsx("span",{className:"loading loading-spinner loading-lg text-primary"})}),c.jsxs("div",{ref:d,className:`relative w-full h-full shadow-lg ${L&&Jt?v?"cursor-grabbing":"cursor-grab":""} ${ke?"opacity-0":"opacity-100"} transition-opacity duration-300`,style:{transformStyle:"preserve-3d",transition:"transform 0.6s ease-in-out, opacity 0.3s ease-in-out",transform:I?"rotateY(180deg)":"rotateY(0deg)"},onMouseDown:Xt,onMouseMove:Gt,onMouseUp:Vt,onMouseLeave:Kt,onTouchStart:Ft,onTouchMove:qt,onTouchEnd:Zt,onDragOver:x=>{x.preventDefault(),u==="front"&&j(!0)},onDragLeave:x=>{x.preventDefault(),j(!1)},onDrop:x=>{if(x.preventDefault(),j(!1),u==="front"&&t){const N=x.dataTransfer.files[0];N&&N.type.startsWith("image/")&&t(N)}},children:[c.jsx("canvas",{ref:y,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"}}),c.jsx("canvas",{ref:k,className:"absolute inset-0 w-full h-full",style:{backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden",transform:"rotateY(180deg)"}}),u==="front"&&!o.original&&c.jsx("div",{className:`absolute flex flex-col items-center justify-center transition-colors duration-300 ease-in-out pointer-events-none ${D?"bg-primary/20":"hover:bg-base-content/5"}`,style:{left:`${(O.front.portrait.x-O.front.portrait.radiusX)/H.width*100}%`,top:`${(O.front.portrait.y-O.front.portrait.radiusY)/H.height*100}%`,width:`${O.front.portrait.radiusX*2/H.width*100}%`,height:`${O.front.portrait.radiusY*2/H.height*100}%`,borderRadius:"50%",backfaceVisibility:"hidden",WebkitBackfaceVisibility:"hidden"},children:c.jsxs("button",{className:"btn btn-dash hover:btn-dash hover:border-base-content/60 flex flex-col items-center gap-0.5 sm:gap-1 h-auto py-1.5 px-2.5 sm:py-3 sm:px-4 bg-base-100/20 hover:bg-base-100/30",children:[c.jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",className:"w-7 h-6 sm:w-10 sm:h-9 text-base-content/50",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:1.5,strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("circle",{cx:"12",cy:"8",r:"4"}),c.jsx("path",{d:"M4 21c0-4 4-6 8-6s8 2 8 6"})]}),c.jsx("span",{className:"text-[10px] sm:text-xs text-center leading-tight whitespace-pre-line",children:n==="de"?`Foto
|
|
15
15
|
hochladen`:`Upload
|
|
16
16
|
photo`})]})})]})]})]})}function Fn(){const e=g.useRef(null),t=g.useRef(null);return{frontCanvasRef:e,backCanvasRef:t}}const qn=`
|
|
17
17
|
// Translations for banner text
|
|
@@ -488,4 +488,4 @@ self.onmessage = async (e) => {
|
|
|
488
488
|
});
|
|
489
489
|
}
|
|
490
490
|
};
|
|
491
|
-
`;let Xe=null,gt=null;function Zn(){if(!Xe){const e=new Blob([qn],{type:"application/javascript"});gt=URL.createObjectURL(e),Xe=new Worker(gt,{type:"module"})}return Xe}async function Ge(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function mt(e,t){const n=new Uint8Array(e);let a="";for(let r=0;r<n.length;r++)a+=String.fromCharCode(n[r]);return`data:${t};base64,${btoa(a)}`}async function
|
|
491
|
+
`;let Xe=null,gt=null;function Zn(){if(!Xe){const e=new Blob([qn],{type:"application/javascript"});gt=URL.createObjectURL(e),Xe=new Worker(gt,{type:"module"})}return Xe}async function Ge(e){const n=await(await fetch(e)).blob();return URL.createObjectURL(n)}function mt(e,t){const n=new Uint8Array(e);let a="";for(let r=0;r<n.length;r++)a+=String.fromCharCode(n[r]);return`data:${t};base64,${btoa(a)}`}async function Yt(e){const{frontTemplateSrc:t,backTemplateSrc:n,templateWidth:a,templateHeight:r,layout:l,portrait:i,portraitZoom:s=1,portraitPanX:o=0,portraitPanY:u=0,templateHue:h=160,name:f,email:p,phone:m,description:y,language:k="de",hours:d=1}=e,[I,E]=await Promise.all([Ge(t),Ge(n)]);let v=null;return i&&(v=await Ge(i)),new Promise((S,L)=>{const P=Zn(),D=setTimeout(()=>{P.removeEventListener("message",j),P.removeEventListener("error",R),URL.revokeObjectURL(I),URL.revokeObjectURL(E),v&&URL.revokeObjectURL(v),L(new Error("PDF generation timed out. Please try again."))},6e4),j=C=>{if(clearTimeout(D),P.removeEventListener("message",j),P.removeEventListener("error",R),URL.revokeObjectURL(I),URL.revokeObjectURL(E),v&&URL.revokeObjectURL(v),C.data.type==="success")try{const{frontImageData:Y,backImageData:q,width:H,height:O}=C.data;if(!Y||!q||!H||!O){L(new Error("Invalid response from worker"));return}const Z=mt(Y,"image/jpeg"),oe=mt(q,"image/jpeg"),J=138.6,be=72.9,G=J,Q=be,K=new an.jsPDF({orientation:G>Q?"landscape":"portrait",unit:"mm",format:[G,Q]});K.addImage(Z,"JPEG",0,0,G,Q),K.addPage([G,Q]),K.addImage(oe,"JPEG",0,0,G,Q);const xe=K.output("blob");S(xe)}catch(Y){L(Y)}else L(new Error(C.data.error))},R=C=>{P.removeEventListener("message",j),P.removeEventListener("error",R),URL.revokeObjectURL(I),URL.revokeObjectURL(E),v&&URL.revokeObjectURL(v),L(new Error(C.message))};P.addEventListener("message",j),P.addEventListener("error",R),P.postMessage({type:"generate",frontTemplateUrl:I,backTemplateUrl:E,portraitUrl:v,templateWidth:a,templateHeight:r,templateHue:h,portraitZoom:s,portraitPanX:o,portraitPanY:u,layout:{front:{portrait:l.front.portrait,namePlate:l.front.namePlate},back:{namePlate:l.back.namePlate,contactInfo:l.back.contactInfo,description:l.back.description,signature:l.back.signature}},name:f,email:p,phone:m,description:y,language:k,hours:d})})}function _t(e,t){const n=URL.createObjectURL(e),a=document.createElement("a");a.href=n,a.download=t,document.body.appendChild(a),a.click(),document.body.removeChild(a),URL.revokeObjectURL(n)}async function Wt(e){const t=await Yt(e);_t(t,e.filename)}function Jn(){const e=w(d=>d.appLanguage),t=w(d=>d.voucherConfig.language),n=w(d=>d.voucherConfig.hours),a=w(d=>d.voucherConfig.description),r=w(d=>d.voucherConfig.templateHue),l=w(d=>d.personalInfo),i=w(d=>d.portrait),s=w(d=>d.isExporting),o=w(d=>d.setIsExporting),u=re(e),h=nt(),f=at(),p=i.useEnhanced&&i.enhanced?i.enhanced:i.original,m=tt(t,n,a),y=l.name.trim().length>0&&l.email.trim().length>0&&l.phone.trim().length>0&&i.original!==null,k=async()=>{if(!(!y||s)){o(!0);try{const[d,I]=await Promise.all([qe(n,t,"front"),qe(n,t,"back")]),E=`zeitgutschein-${n}h-${l.name.replace(/\s+/g,"-").toLowerCase()}.pdf`;await Wt({frontTemplateSrc:d,backTemplateSrc:I,templateWidth:h.width,templateHeight:h.height,layout:f,portrait:p,portraitZoom:i.zoom,portraitPanX:i.panX,portraitPanY:i.panY,templateHue:r,name:l.name,email:l.email,phone:l.phone,description:m,filename:E,language:t,hours:n})}catch(d){console.error("PDF export failed:",d)}finally{o(!1)}}};return c.jsxs("button",{className:`btn btn-primary w-full btn-md ${y?"":"btn-disabled"}`,onClick:k,disabled:!y,"aria-busy":s,children:[s?c.jsx("span",{className:"loading loading-spinner loading-sm"}):c.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",className:"h-5 w-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"})}),u.export.button]})}function zt(){const e=w(a=>a.appLanguage),t=w(a=>a.setAppLanguage),n=a=>{t(a)};return c.jsxs("div",{className:"join",children:[c.jsx("button",{className:`join-item btn btn-sm ${e==="de"?"btn-primary":"btn-ghost"}`,onClick:()=>n("de"),children:"DE"}),c.jsx("button",{className:`join-item btn btn-sm ${e==="en"?"btn-primary":"btn-ghost"}`,onClick:()=>n("en"),children:"EN"})]})}function Qn(){const e=w(n=>n.appLanguage),t=re(e);return c.jsxs("div",{className:"navbar bg-currency-green text-currency-cream shadow-lg shrink-0",children:[c.jsx("div",{className:"navbar-start",children:c.jsx("a",{className:"btn btn-ghost text-xl font-currency font-bold",children:t.header.title})}),c.jsx("div",{className:"navbar-center hidden sm:flex",children:c.jsx("span",{className:"text-sm opacity-80",children:t.header.subtitle})}),c.jsx("div",{className:"navbar-end",children:c.jsx(zt,{})})]})}const Be="/",ea={id:"time-voucher-classic-de",name:"Zeitgutschein Classic",type:"time-voucher",category:"classic",images:{front:`${Be}templates/front_hdpi_de.jpg`,back:`${Be}templates/back_hdpi_de.jpg`,width:6144,height:4096},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:ue.front.portrait,name:ue.front.namePlate},back:{name:ue.back.namePlate,contactInfo:ue.back.contactInfo,description:ue.back.description}},languages:["de"]},ta={id:"time-voucher-classic-en",name:"Time Voucher Classic",type:"time-voucher",category:"classic",images:{front:`${Be}templates/front_ldpi_en.png`,back:`${Be}templates/back_ldpi_en.png`,width:1536,height:1024},fields:[{id:"name",type:"text",label:{de:"Name",en:"Name"},required:!0,validation:{minLength:1,maxLength:50}},{id:"hours",type:"select",label:{de:"Stunden",en:"Hours"},required:!0,options:["1","5","10"]},{id:"portrait",type:"image",label:{de:"Portrait",en:"Portrait"},required:!1},{id:"email",type:"text",label:{de:"E-Mail",en:"Email"},required:!1},{id:"phone",type:"text",label:{de:"Telefon",en:"Phone"},required:!1},{id:"description",type:"textarea",label:{de:"Beschreibung",en:"Description"},required:!1,validation:{maxLength:200}}],layout:{front:{portrait:de.front.portrait,name:de.front.namePlate},back:{name:de.back.namePlate,contactInfo:de.back.contactInfo,description:de.back.description}},languages:["en"]},ht=[ea,ta],$t={async listTemplates(e){let t=[...ht];return e!=null&&e.type&&(t=t.filter(n=>n.type===e.type)),e!=null&&e.category&&(t=t.filter(n=>n.category===e.category)),e!=null&&e.language&&(t=t.filter(n=>n.languages.includes(e.language))),t},async getTemplate(e){const t=ht.find(n=>n.id===e);if(!t)throw new Error(`Template not found: ${e}`);return t}};function na(e){return e==="de"?"time-voucher-classic-de":"time-voucher-classic-en"}let De=$t;function aa(e){De=e}function ra(){return De}async function oa(e){return De.listTemplates(e)}async function ia(e){return De.getTemplate(e)}exports.ApiKeyModal=Ot;exports.BillPreview=Kn;exports.ExportButton=Jn;exports.Header=Qn;exports.LAYOUT_HDPI=ue;exports.LAYOUT_LDPI=de;exports.LanguageToggle=zt;exports.PREVIEW_HEIGHT=dn;exports.PREVIEW_WIDTH=un;exports.PersonalInfoForm=Nn;exports.PortraitUpload=zn;exports.TEMPLATE_HEIGHT=ae;exports.TEMPLATE_LAYOUT=Ae;exports.TEMPLATE_WIDTH=ne;exports.TouchSlider=ye;exports.VoucherConfig=$n;exports.applyEngravingEffect=bt;exports.applyHueShift=wt;exports.clearCompositorCache=Pt;exports.clearHueShiftedCache=Lt;exports.composeTemplate=St;exports.composeTemplateFullRes=qe;exports.downloadBlob=_t;exports.drawContactInfo=Nt;exports.drawMultilineText=Bt;exports.drawOvalPortrait=Ct;exports.drawTemplate=ce;exports.drawText=et;exports.enhancePortrait=_n;exports.exportBillAsPDF=Wt;exports.formatDescription=tt;exports.generateBillPDF=Yt;exports.getApiKey=je;exports.getDefaultTemplateId=na;exports.getLayout=at;exports.getRemoveBackgroundEndpoint=Hn;exports.getTemplate=nt;exports.getTemplateById=ia;exports.getTemplateDimensions=pn;exports.getTemplateLayers=Ze;exports.getTemplateProvider=ra;exports.hasApiKey=Pe;exports.hasCustomEndpoint=Mn;exports.listTemplates=oa;exports.loadImage=B;exports.preloadAllTemplates=fn;exports.preloadBaseImages=gn;exports.removeBackground=Ut;exports.renderBackSide=At;exports.renderFrontSide=jt;exports.resizeImage=pt;exports.setApiKey=Mt;exports.setRemoveBackgroundEndpoint=Dn;exports.setTemplateProvider=aa;exports.staticTemplateProvider=$t;exports.t=re;exports.useBillCanvasRefs=Fn;exports.useBillStore=w;
|
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ async function ht(e) {
|
|
|
43
43
|
if (!s) throw new Error("Failed to get canvas context");
|
|
44
44
|
return i.width = r, i.height = c, s.drawImage(t, 0, 0, r, c), i.toDataURL("image/png");
|
|
45
45
|
}
|
|
46
|
-
async function
|
|
46
|
+
async function $e(e, t, n, a = 0) {
|
|
47
47
|
const [r, c] = await Promise.all([
|
|
48
48
|
fe(e),
|
|
49
49
|
fe(t)
|
|
@@ -140,7 +140,7 @@ const me = typeof import.meta < "u" && "/" || "/", F = {
|
|
|
140
140
|
10: "TEN HOURS"
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
-
}, le = 3633, de = 1920,
|
|
143
|
+
}, le = 3633, de = 1920, Me = 0.5, Kn = Math.round(le * Me), Fn = Math.round(de * Me), bt = 320, wt = 335, K = {
|
|
144
144
|
// Number badge positions (4 corners) - centered at ornament positions
|
|
145
145
|
badges: {
|
|
146
146
|
topLeft: { x: 286, y: 235 },
|
|
@@ -178,7 +178,7 @@ let G = {
|
|
|
178
178
|
backFrame: null,
|
|
179
179
|
badges: { 1: null, 5: null, 10: null }
|
|
180
180
|
};
|
|
181
|
-
async function
|
|
181
|
+
async function qn() {
|
|
182
182
|
const [e, t, n, a, r, c] = await Promise.all([
|
|
183
183
|
C(F.background),
|
|
184
184
|
C(F.frontFrame),
|
|
@@ -258,7 +258,7 @@ async function Jt(e, t, n) {
|
|
|
258
258
|
const a = `${e}-${t}-${n}`;
|
|
259
259
|
if (Le.has(a))
|
|
260
260
|
return Le.get(a);
|
|
261
|
-
const r = G.background || await C(F.background), c = n === "front" ? G.frontFrame || await C(F.frontFrame) : G.backFrame || await C(F.backFrame), i = G.badges[e] || await C(he[e]), s = xt(e, t, n,
|
|
261
|
+
const r = G.background || await C(F.background), c = n === "front" ? G.frontFrame || await C(F.frontFrame) : G.backFrame || await C(F.backFrame), i = G.badges[e] || await C(he[e]), s = xt(e, t, n, Me, r, c, i);
|
|
262
262
|
return Le.set(a, s), s;
|
|
263
263
|
}
|
|
264
264
|
async function st(e, t, n) {
|
|
@@ -272,16 +272,16 @@ async function st(e, t, n) {
|
|
|
272
272
|
}
|
|
273
273
|
return se.set(a, s), s;
|
|
274
274
|
}
|
|
275
|
-
function
|
|
275
|
+
function Zn() {
|
|
276
276
|
return {
|
|
277
277
|
width: le,
|
|
278
278
|
height: de
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
|
-
function
|
|
281
|
+
function Qt() {
|
|
282
282
|
Le.clear(), se.clear(), Ke.clear(), Fe.clear(), qe.clear();
|
|
283
283
|
}
|
|
284
|
-
async function ct(e, t, n = "front", a =
|
|
284
|
+
async function ct(e, t, n = "front", a = Me) {
|
|
285
285
|
const r = `bg-${a}`;
|
|
286
286
|
let c = Ke.get(r);
|
|
287
287
|
if (!c) {
|
|
@@ -313,24 +313,24 @@ async function Jn() {
|
|
|
313
313
|
a.push(Jt(r, c, i));
|
|
314
314
|
await Promise.all(a);
|
|
315
315
|
}
|
|
316
|
-
const
|
|
317
|
-
function
|
|
318
|
-
ce.clear();
|
|
316
|
+
const Re = /* @__PURE__ */ new Map(), ce = /* @__PURE__ */ new Map();
|
|
317
|
+
function en() {
|
|
318
|
+
ce.clear(), Re.clear();
|
|
319
319
|
}
|
|
320
320
|
async function C(e) {
|
|
321
|
-
return
|
|
321
|
+
return Re.has(e) ? Re.get(e) : new Promise((t, n) => {
|
|
322
322
|
const a = new Image();
|
|
323
323
|
a.crossOrigin = "anonymous", a.onload = () => {
|
|
324
|
-
|
|
324
|
+
Re.set(e, a), t(a);
|
|
325
325
|
}, a.onerror = n, a.src = e;
|
|
326
326
|
});
|
|
327
327
|
}
|
|
328
328
|
function pe(e, t, n, a) {
|
|
329
329
|
e.drawImage(t, 0, 0, n, a);
|
|
330
330
|
}
|
|
331
|
-
const
|
|
331
|
+
const tn = 29, nn = 5;
|
|
332
332
|
async function It(e, t, n, a) {
|
|
333
|
-
if (Math.abs(t -
|
|
333
|
+
if (Math.abs(t - tn) <= nn)
|
|
334
334
|
return C(e);
|
|
335
335
|
const r = `${e}:${t}:${n}x${a}`;
|
|
336
336
|
if (ce.has(r))
|
|
@@ -347,10 +347,10 @@ async function It(e, t, n, a) {
|
|
|
347
347
|
}
|
|
348
348
|
return ce.set(r, l), C(l);
|
|
349
349
|
}
|
|
350
|
-
function
|
|
350
|
+
function an(e, t, n, a, r, c = "de") {
|
|
351
351
|
e.save(), e.beginPath(), e.ellipse(t, n, a, r, 0, 0, Math.PI * 2), e.closePath(), e.setLineDash([20, 10]), e.strokeStyle = "rgba(100, 100, 100, 0.4)", e.lineWidth = 3, e.stroke(), e.restore();
|
|
352
352
|
}
|
|
353
|
-
function
|
|
353
|
+
function rn(e, t, n, a, r, c, i = 1, s = 0, o = 0) {
|
|
354
354
|
e.save(), e.beginPath(), e.ellipse(n, a, r, c, 0, 0, Math.PI * 2), e.closePath(), e.clip();
|
|
355
355
|
const l = t.width / t.height, m = r / c, p = r * 2, h = c * 2;
|
|
356
356
|
let g, w;
|
|
@@ -361,7 +361,7 @@ function an(e, t, n, a, r, c, i = 1, s = 0, o = 0) {
|
|
|
361
361
|
function kt(e, t, n, a = "#2a3a2a") {
|
|
362
362
|
e.save(), e.font = `${n.fontSize}px "Times New Roman", serif`, e.textAlign = n.align || "center", e.textBaseline = "middle", e.fillStyle = a, n.maxWidth ? e.fillText(t, n.x, n.y, n.maxWidth) : e.fillText(t, n.x, n.y), e.restore();
|
|
363
363
|
}
|
|
364
|
-
function
|
|
364
|
+
function on(e, t, n, a = "#2a3a2a") {
|
|
365
365
|
e.save(), e.font = `${n.fontSize}px "Times New Roman", serif`, e.textAlign = n.align || "center", e.textBaseline = "top", e.fillStyle = a;
|
|
366
366
|
const r = n.maxWidth || 400, c = n.lineHeight || n.fontSize * 1.4, i = t.split(" "), s = [];
|
|
367
367
|
let o = "";
|
|
@@ -376,7 +376,7 @@ function rn(e, t, n, a = "#2a3a2a") {
|
|
|
376
376
|
e.fillText(p, n.x, m), m += c;
|
|
377
377
|
e.restore();
|
|
378
378
|
}
|
|
379
|
-
function
|
|
379
|
+
function sn(e, t, n, a, r, c = "#2a3a2a") {
|
|
380
380
|
e.save(), e.font = `${r.fontSize}px "Times New Roman", serif`, e.textAlign = r.align || "center", e.textBaseline = "middle", e.fillStyle = c;
|
|
381
381
|
const i = r.lineHeight || r.fontSize * 1.8, s = [t, n, a].filter(Boolean), o = (s.length - 1) * i;
|
|
382
382
|
let l = r.y - o / 2;
|
|
@@ -384,10 +384,10 @@ function on(e, t, n, a, r, c = "#2a3a2a") {
|
|
|
384
384
|
m && (e.fillText(m, r.x, l), l += i);
|
|
385
385
|
e.restore();
|
|
386
386
|
}
|
|
387
|
-
function
|
|
387
|
+
function cn(e, t, n, a = "#2a3a2a") {
|
|
388
388
|
e.save(), e.strokeStyle = a, e.lineWidth = Math.max(2, t.labelFontSize / 16), e.beginPath(), e.moveTo(t.x - t.width / 2, t.y), e.lineTo(t.x + t.width / 2, t.y), e.stroke(), e.font = `${t.labelFontSize}px "Times New Roman", serif`, e.textAlign = "center", e.textBaseline = "top", e.fillStyle = a, e.fillText(n, t.x, t.y + t.labelFontSize * 0.3), e.restore();
|
|
389
389
|
}
|
|
390
|
-
async function
|
|
390
|
+
async function ln(e, t, n, a, r, c, i, s, o, l = 1, m = 0, p = 0, h = 0, g = 1, w = "de") {
|
|
391
391
|
const I = e.getContext("2d");
|
|
392
392
|
if (!I) return;
|
|
393
393
|
const d = document.createElement("canvas");
|
|
@@ -401,7 +401,7 @@ async function cn(e, t, n, a, r, c, i, s, o, l = 1, m = 0, p = 0, h = 0, g = 1,
|
|
|
401
401
|
if (pe(k, x, s, o), r)
|
|
402
402
|
try {
|
|
403
403
|
const S = await C(r);
|
|
404
|
-
|
|
404
|
+
rn(
|
|
405
405
|
k,
|
|
406
406
|
S,
|
|
407
407
|
i.portrait.x,
|
|
@@ -416,7 +416,7 @@ async function cn(e, t, n, a, r, c, i, s, o, l = 1, m = 0, p = 0, h = 0, g = 1,
|
|
|
416
416
|
console.error("Failed to load portrait:", S);
|
|
417
417
|
}
|
|
418
418
|
else
|
|
419
|
-
|
|
419
|
+
an(
|
|
420
420
|
k,
|
|
421
421
|
i.portrait.x,
|
|
422
422
|
i.portrait.y,
|
|
@@ -429,7 +429,7 @@ async function cn(e, t, n, a, r, c, i, s, o, l = 1, m = 0, p = 0, h = 0, g = 1,
|
|
|
429
429
|
const L = s / 3633;
|
|
430
430
|
vt(k, g, w, L), c && kt(k, c, i.namePlate), e.width = s, e.height = o, I.drawImage(d, 0, 0);
|
|
431
431
|
}
|
|
432
|
-
async function
|
|
432
|
+
async function dn(e, t, n, a, r, c, i, s, o, l, m, p = 0, h = 1, g = "de") {
|
|
433
433
|
const w = e.getContext("2d");
|
|
434
434
|
if (!w) return;
|
|
435
435
|
const I = document.createElement("canvas");
|
|
@@ -444,19 +444,19 @@ async function ln(e, t, n, a, r, c, i, s, o, l, m, p = 0, h = 1, g = "de") {
|
|
|
444
444
|
const x = await C(a);
|
|
445
445
|
pe(d, x, l, m);
|
|
446
446
|
const P = l / 3633;
|
|
447
|
-
if (vt(d, h, g, P), o.contactInfo && (r || c || i) &&
|
|
447
|
+
if (vt(d, h, g, P), o.contactInfo && (r || c || i) && sn(d, r, c, i, o.contactInfo), o.description && s && on(d, s, o.description), r && kt(d, r, o.namePlate), o.signature) {
|
|
448
448
|
const L = g === "de" ? "Unterschrift" : "Signature";
|
|
449
|
-
|
|
449
|
+
cn(d, o.signature, L);
|
|
450
450
|
}
|
|
451
451
|
e.width = l, e.height = m, w.drawImage(I, 0, 0);
|
|
452
452
|
}
|
|
453
|
-
const
|
|
454
|
-
async function
|
|
453
|
+
const Ne = "money-generator-portrait", Be = "money-generator-bg-removed";
|
|
454
|
+
async function un(e) {
|
|
455
455
|
try {
|
|
456
|
-
if (localStorage.removeItem(
|
|
456
|
+
if (localStorage.removeItem(Ne), !e) return;
|
|
457
457
|
const t = await ht(e);
|
|
458
458
|
try {
|
|
459
|
-
localStorage.setItem(
|
|
459
|
+
localStorage.setItem(Ne, t);
|
|
460
460
|
} catch (n) {
|
|
461
461
|
console.warn("Could not persist portrait to localStorage:", n);
|
|
462
462
|
}
|
|
@@ -464,12 +464,12 @@ async function dn(e) {
|
|
|
464
464
|
console.warn("Error processing portrait for storage:", t);
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
|
-
async function
|
|
467
|
+
async function gn(e) {
|
|
468
468
|
try {
|
|
469
|
-
if (localStorage.removeItem(
|
|
469
|
+
if (localStorage.removeItem(Be), !e) return;
|
|
470
470
|
const t = await ht(e);
|
|
471
471
|
try {
|
|
472
|
-
localStorage.setItem(
|
|
472
|
+
localStorage.setItem(Be, t);
|
|
473
473
|
} catch (n) {
|
|
474
474
|
console.warn("Could not persist bg-removed image to localStorage:", n);
|
|
475
475
|
}
|
|
@@ -477,30 +477,30 @@ async function un(e) {
|
|
|
477
477
|
console.warn("Error processing bg-removed image for storage:", t);
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
|
-
function
|
|
480
|
+
function mn() {
|
|
481
481
|
try {
|
|
482
|
-
return localStorage.getItem(
|
|
482
|
+
return localStorage.getItem(Ne);
|
|
483
483
|
} catch {
|
|
484
484
|
return null;
|
|
485
485
|
}
|
|
486
486
|
}
|
|
487
|
-
function
|
|
487
|
+
function hn() {
|
|
488
488
|
try {
|
|
489
|
-
return localStorage.getItem(
|
|
489
|
+
return localStorage.getItem(Be);
|
|
490
490
|
} catch {
|
|
491
491
|
return null;
|
|
492
492
|
}
|
|
493
493
|
}
|
|
494
|
-
function
|
|
494
|
+
function pn() {
|
|
495
495
|
try {
|
|
496
|
-
localStorage.removeItem(
|
|
496
|
+
localStorage.removeItem(Ne), localStorage.removeItem(Be);
|
|
497
497
|
} catch {
|
|
498
498
|
}
|
|
499
499
|
}
|
|
500
|
-
function
|
|
500
|
+
function fn() {
|
|
501
501
|
return (typeof navigator < "u" ? navigator.language : "de").toLowerCase().startsWith("de") ? "de" : "en";
|
|
502
502
|
}
|
|
503
|
-
const
|
|
503
|
+
const Ce = fn(), lt = {
|
|
504
504
|
personalInfo: {
|
|
505
505
|
name: "",
|
|
506
506
|
email: "",
|
|
@@ -509,7 +509,7 @@ const Be = pn(), lt = {
|
|
|
509
509
|
voucherConfig: {
|
|
510
510
|
hours: 1,
|
|
511
511
|
description: "",
|
|
512
|
-
language:
|
|
512
|
+
language: Ce,
|
|
513
513
|
// Bill/template language - follows browser
|
|
514
514
|
templateHue: 29
|
|
515
515
|
// Default to original beige color (~29°)
|
|
@@ -531,7 +531,7 @@ const Be = pn(), lt = {
|
|
|
531
531
|
currentSide: "front",
|
|
532
532
|
isEnhancing: !1,
|
|
533
533
|
isExporting: !1,
|
|
534
|
-
appLanguage:
|
|
534
|
+
appLanguage: Ce
|
|
535
535
|
// UI language - follows browser
|
|
536
536
|
}, y = Yt()(
|
|
537
537
|
Wt(
|
|
@@ -543,7 +543,7 @@ const Be = pn(), lt = {
|
|
|
543
543
|
setVoucherConfig: (t) => e((n) => ({
|
|
544
544
|
voucherConfig: { ...n.voucherConfig, ...t }
|
|
545
545
|
})),
|
|
546
|
-
setPortrait: (t, n = null) => (
|
|
546
|
+
setPortrait: (t, n = null) => (un(t), e((a) => ({
|
|
547
547
|
portrait: {
|
|
548
548
|
...a.portrait,
|
|
549
549
|
original: t,
|
|
@@ -587,7 +587,7 @@ const Be = pn(), lt = {
|
|
|
587
587
|
rawImage: t
|
|
588
588
|
}
|
|
589
589
|
})),
|
|
590
|
-
setPortraitBgRemoved: (t, n) => (n !== void 0 &&
|
|
590
|
+
setPortraitBgRemoved: (t, n) => (n !== void 0 && gn(n), e((a) => ({
|
|
591
591
|
portrait: {
|
|
592
592
|
...a.portrait,
|
|
593
593
|
bgRemoved: t,
|
|
@@ -625,17 +625,17 @@ const Be = pn(), lt = {
|
|
|
625
625
|
setHours: (t) => e((n) => ({
|
|
626
626
|
voucherConfig: { ...n.voucherConfig, hours: t }
|
|
627
627
|
})),
|
|
628
|
-
setTemplateHue: (t) => (Qt(), e((n) => ({
|
|
628
|
+
setTemplateHue: (t) => (en(), Qt(), e((n) => ({
|
|
629
629
|
voucherConfig: { ...n.voucherConfig, templateHue: t }
|
|
630
630
|
}))),
|
|
631
|
-
reset: () => (
|
|
631
|
+
reset: () => (pn(), e(lt))
|
|
632
632
|
}),
|
|
633
633
|
{
|
|
634
634
|
name: "money-generator-storage",
|
|
635
635
|
// Migrate old storage - preserve user settings
|
|
636
636
|
migrate: (e) => {
|
|
637
637
|
const t = e;
|
|
638
|
-
return t != null && t.voucherConfig && (t.voucherConfig.templateHue === void 0 && (t.voucherConfig.templateHue = 29), t.voucherConfig.hours = 1, t.voucherConfig.language =
|
|
638
|
+
return t != null && t.voucherConfig && (t.voucherConfig.templateHue === void 0 && (t.voucherConfig.templateHue = 29), t.voucherConfig.hours = 1, t.voucherConfig.language = Ce), t && (t.appLanguage = Ce), t;
|
|
639
639
|
},
|
|
640
640
|
version: 2,
|
|
641
641
|
// Bump version to trigger migration
|
|
@@ -675,7 +675,7 @@ const Be = pn(), lt = {
|
|
|
675
675
|
)
|
|
676
676
|
);
|
|
677
677
|
if (typeof window < "u") {
|
|
678
|
-
const e =
|
|
678
|
+
const e = mn(), t = hn();
|
|
679
679
|
e && setTimeout(() => {
|
|
680
680
|
const n = y.getState();
|
|
681
681
|
if (!n.portrait.original) {
|
|
@@ -697,7 +697,7 @@ if (typeof window < "u") {
|
|
|
697
697
|
}
|
|
698
698
|
}, 0);
|
|
699
699
|
}
|
|
700
|
-
const
|
|
700
|
+
const bn = {
|
|
701
701
|
header: {
|
|
702
702
|
title: "Money Generator",
|
|
703
703
|
subtitle: "Erstelle deinen persönlichen Zeitgutschein"
|
|
@@ -756,7 +756,7 @@ const fn = {
|
|
|
756
756
|
10: "zehn Stunden"
|
|
757
757
|
}
|
|
758
758
|
}
|
|
759
|
-
},
|
|
759
|
+
}, wn = {
|
|
760
760
|
header: {
|
|
761
761
|
title: "Money Generator",
|
|
762
762
|
subtitle: "Create your personal time voucher"
|
|
@@ -815,9 +815,9 @@ const fn = {
|
|
|
815
815
|
10: "ten hours"
|
|
816
816
|
}
|
|
817
817
|
}
|
|
818
|
-
},
|
|
818
|
+
}, yn = { de: bn, en: wn };
|
|
819
819
|
function ue(e) {
|
|
820
|
-
return
|
|
820
|
+
return yn[e];
|
|
821
821
|
}
|
|
822
822
|
function Tt(e, t, n) {
|
|
823
823
|
if (n && n.trim())
|
|
@@ -825,14 +825,14 @@ function Tt(e, t, n) {
|
|
|
825
825
|
const a = ue(e), r = a.bill.bannerText[t] || a.bill.bannerText[1];
|
|
826
826
|
return a.bill.descriptionText.replace("{bannerText}", r);
|
|
827
827
|
}
|
|
828
|
-
function
|
|
828
|
+
function vn(e) {
|
|
829
829
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);
|
|
830
830
|
}
|
|
831
|
-
function
|
|
831
|
+
function xn(e) {
|
|
832
832
|
return e.replace(/\D/g, "").length >= 6;
|
|
833
833
|
}
|
|
834
834
|
function Qn({ focusField: e, onFocused: t, onFormFocusChange: n } = {}) {
|
|
835
|
-
const a = y((d) => d.appLanguage), r = y((d) => d.personalInfo), c = y((d) => d.setPersonalInfo), i = ue(a), [s, o] = H(!1), [l, m] = H(!1), p = s && r.email.trim() && !
|
|
835
|
+
const a = y((d) => d.appLanguage), r = y((d) => d.personalInfo), c = y((d) => d.setPersonalInfo), i = ue(a), [s, o] = H(!1), [l, m] = H(!1), p = s && r.email.trim() && !vn(r.email), h = l && r.phone.trim() && !xn(r.phone), g = W(null), w = W(null), I = W(null);
|
|
836
836
|
return j(() => {
|
|
837
837
|
if (e) {
|
|
838
838
|
const d = e === "name" ? g : e === "email" ? w : I;
|
|
@@ -913,7 +913,7 @@ function Qn({ focusField: e, onFocused: t, onFormFocusChange: n } = {}) {
|
|
|
913
913
|
] })
|
|
914
914
|
] });
|
|
915
915
|
}
|
|
916
|
-
const Xe = {},
|
|
916
|
+
const Xe = {}, In = "https://api.stability.ai/v1/generation", kn = "https://api.stability.ai/v2beta/stable-image/edit/remove-background", Et = "stability_api_key";
|
|
917
917
|
let be = null;
|
|
918
918
|
function ea(e) {
|
|
919
919
|
be = e;
|
|
@@ -924,7 +924,7 @@ function ta() {
|
|
|
924
924
|
function na() {
|
|
925
925
|
return be !== null;
|
|
926
926
|
}
|
|
927
|
-
const
|
|
927
|
+
const Tn = {
|
|
928
928
|
vintage: "portrait in the style of vintage currency engraving, fine line work, crosshatching, sepia tones, detailed stippling, classic bank note portrait style",
|
|
929
929
|
engraved: "portrait as detailed intaglio engraving, currency bill style, fine parallel lines, high contrast, official government portrait",
|
|
930
930
|
currency: "portrait rendered as US dollar bill engraving, official currency portrait style, green tint, fine line engraving technique"
|
|
@@ -939,7 +939,7 @@ const kn = {
|
|
|
939
939
|
{ width: 832, height: 1216 },
|
|
940
940
|
{ width: 896, height: 1152 }
|
|
941
941
|
];
|
|
942
|
-
function
|
|
942
|
+
function En(e, t) {
|
|
943
943
|
const n = e / t;
|
|
944
944
|
let a = dt[0], r = 1 / 0;
|
|
945
945
|
for (const c of dt) {
|
|
@@ -948,11 +948,11 @@ function Tn(e, t) {
|
|
|
948
948
|
}
|
|
949
949
|
return a;
|
|
950
950
|
}
|
|
951
|
-
function
|
|
951
|
+
function Pn(e) {
|
|
952
952
|
return new Promise((t, n) => {
|
|
953
953
|
const a = new Image();
|
|
954
954
|
a.onload = () => {
|
|
955
|
-
const r =
|
|
955
|
+
const r = En(a.width, a.height), c = document.createElement("canvas");
|
|
956
956
|
c.width = r.width, c.height = r.height;
|
|
957
957
|
const i = c.getContext("2d");
|
|
958
958
|
if (!i) {
|
|
@@ -977,7 +977,7 @@ function Qe() {
|
|
|
977
977
|
const e = typeof import.meta < "u" && (Xe == null ? void 0 : Xe.VITE_STABILITY_API_KEY) || typeof process < "u" && ((t = process.env) == null ? void 0 : t.NEXT_PUBLIC_STABILITY_API_KEY);
|
|
978
978
|
return e && e !== "your-api-key-here" ? e : typeof localStorage < "u" ? localStorage.getItem(Et) : null;
|
|
979
979
|
}
|
|
980
|
-
function
|
|
980
|
+
function Sn(e) {
|
|
981
981
|
localStorage.setItem(Et, e);
|
|
982
982
|
}
|
|
983
983
|
function je() {
|
|
@@ -987,9 +987,9 @@ async function aa(e) {
|
|
|
987
987
|
const t = Qe();
|
|
988
988
|
if (!t)
|
|
989
989
|
throw new Error("No Stability AI API key configured");
|
|
990
|
-
const { imageDataUrl: n, style: a, strength: r = 0.35 } = e, c = await
|
|
991
|
-
s.append("init_image", i, "portrait.png"), s.append("init_image_mode", "IMAGE_STRENGTH"), s.append("image_strength", String(1 - r)), s.append("text_prompts[0][text]",
|
|
992
|
-
const l = await fetch(`${
|
|
990
|
+
const { imageDataUrl: n, style: a, strength: r = 0.35 } = e, c = await Pn(n), i = Pt(c), s = new FormData();
|
|
991
|
+
s.append("init_image", i, "portrait.png"), s.append("init_image_mode", "IMAGE_STRENGTH"), s.append("image_strength", String(1 - r)), s.append("text_prompts[0][text]", Tn[a]), s.append("text_prompts[0][weight]", "1"), s.append("cfg_scale", "7"), s.append("samples", "1"), s.append("steps", "30");
|
|
992
|
+
const l = await fetch(`${In}/stable-diffusion-xl-1024-v1-0/image-to-image`, {
|
|
993
993
|
method: "POST",
|
|
994
994
|
headers: {
|
|
995
995
|
Authorization: `Bearer ${t}`,
|
|
@@ -1006,7 +1006,7 @@ async function aa(e) {
|
|
|
1006
1006
|
throw new Error("No image generated");
|
|
1007
1007
|
return `data:image/png;base64,${m.artifacts[0].base64}`;
|
|
1008
1008
|
}
|
|
1009
|
-
async function
|
|
1009
|
+
async function Ln(e) {
|
|
1010
1010
|
if (be) {
|
|
1011
1011
|
const i = await fetch(be, {
|
|
1012
1012
|
method: "POST",
|
|
@@ -1026,7 +1026,7 @@ async function Sn(e) {
|
|
|
1026
1026
|
throw new Error("No Stability AI API key configured");
|
|
1027
1027
|
const n = Pt(e), a = new FormData();
|
|
1028
1028
|
a.append("image", n, "image.png"), a.append("output_format", "png");
|
|
1029
|
-
const r = await fetch(
|
|
1029
|
+
const r = await fetch(kn, {
|
|
1030
1030
|
method: "POST",
|
|
1031
1031
|
headers: {
|
|
1032
1032
|
Authorization: `Bearer ${t}`,
|
|
@@ -1044,7 +1044,7 @@ async function Sn(e) {
|
|
|
1044
1044
|
o.onload = () => i(o.result), o.onerror = () => s(new Error("Failed to read result")), o.readAsDataURL(c);
|
|
1045
1045
|
});
|
|
1046
1046
|
}
|
|
1047
|
-
function
|
|
1047
|
+
function Rn() {
|
|
1048
1048
|
const [e, t] = H(!1), [n, a] = H(!1), [r, c] = H(null), [i, s] = H(() => je());
|
|
1049
1049
|
j(() => {
|
|
1050
1050
|
s(je());
|
|
@@ -1054,7 +1054,7 @@ function Ln() {
|
|
|
1054
1054
|
return () => clearTimeout(h);
|
|
1055
1055
|
}, []);
|
|
1056
1056
|
const o = O(() => c(null), []), l = O((h) => {
|
|
1057
|
-
|
|
1057
|
+
Sn(h), s(!0), c(null);
|
|
1058
1058
|
}, []), m = O(
|
|
1059
1059
|
async (h, g = 0.5, w = 40) => {
|
|
1060
1060
|
t(!0), c(null);
|
|
@@ -1072,7 +1072,7 @@ function Ln() {
|
|
|
1072
1072
|
async (h) => {
|
|
1073
1073
|
a(!0), c(null);
|
|
1074
1074
|
try {
|
|
1075
|
-
return await
|
|
1075
|
+
return await Ln(h);
|
|
1076
1076
|
} catch (g) {
|
|
1077
1077
|
const w = g instanceof Error ? g.message : "Background removal failed";
|
|
1078
1078
|
throw c(w), g;
|
|
@@ -1093,7 +1093,7 @@ function Ln() {
|
|
|
1093
1093
|
clearError: o
|
|
1094
1094
|
};
|
|
1095
1095
|
}
|
|
1096
|
-
function
|
|
1096
|
+
function Nn({ isOpen: e, onClose: t, onSubmit: n }) {
|
|
1097
1097
|
const a = y((l) => l.appLanguage), [r, c] = H("");
|
|
1098
1098
|
if (!e) return null;
|
|
1099
1099
|
const i = (l) => {
|
|
@@ -1243,7 +1243,7 @@ function Se({
|
|
|
1243
1243
|
);
|
|
1244
1244
|
}
|
|
1245
1245
|
function ra() {
|
|
1246
|
-
const e = y((f) => f.appLanguage), t = y((f) => f.portrait), n = y((f) => f.setPortrait), a = y((f) => f.setPortraitZoom), r = y((f) => f.setPortraitPan), c = y((f) => f.setPortraitRawImage), i = y((f) => f.setPortraitBgRemoved), s = y((f) => f.setPortraitBgOpacity), o = y((f) => f.setPortraitBgBlur), l = y((f) => f.setPortraitEngravingIntensity), { enhance: m, removeBg: p, isEnhancing: h, isRemovingBg: g, error: w, hasKey: I, setApiKey: d } =
|
|
1246
|
+
const e = y((f) => f.appLanguage), t = y((f) => f.portrait), n = y((f) => f.setPortrait), a = y((f) => f.setPortraitZoom), r = y((f) => f.setPortraitPan), c = y((f) => f.setPortraitRawImage), i = y((f) => f.setPortraitBgRemoved), s = y((f) => f.setPortraitBgOpacity), o = y((f) => f.setPortraitBgBlur), l = y((f) => f.setPortraitEngravingIntensity), { enhance: m, removeBg: p, isEnhancing: h, isRemovingBg: g, error: w, hasKey: I, setApiKey: d } = Rn(), k = ue(e), E = W(null), [x, P] = H(!1), [L, S] = H(!1), D = W(null), A = W(null), R = t.rawImage, N = t.bgRemovedImage, $ = t.bgRemoved, ee = t.bgOpacity, U = t.bgBlur, _ = t.engravingIntensity;
|
|
1247
1247
|
j(() => {
|
|
1248
1248
|
t.original && !t.rawImage && c(t.original);
|
|
1249
1249
|
}, [t.original, t.rawImage, c]), j(() => () => {
|
|
@@ -1296,7 +1296,7 @@ function ra() {
|
|
|
1296
1296
|
const f = y.getState(), T = f.portrait, Y = f.voucherConfig.templateHue;
|
|
1297
1297
|
if (!T.rawImage) return;
|
|
1298
1298
|
let M;
|
|
1299
|
-
T.bgRemoved && T.bgRemovedImage ? M = await
|
|
1299
|
+
T.bgRemoved && T.bgRemovedImage ? M = await $e(T.bgRemovedImage, T.rawImage, T.bgOpacity, T.bgBlur) : M = T.rawImage, T.engravingIntensity > 0 && (M = await re(M, T.engravingIntensity, Y)), n(M);
|
|
1300
1300
|
}, [re, n]);
|
|
1301
1301
|
j(() => {
|
|
1302
1302
|
if (ie.current === te) return;
|
|
@@ -1304,7 +1304,7 @@ function ra() {
|
|
|
1304
1304
|
const f = y.getState().portrait;
|
|
1305
1305
|
f.engravingIntensity > 0 && f.rawImage && (D.current && clearTimeout(D.current), D.current = setTimeout(oe, 150));
|
|
1306
1306
|
}, [te, oe]);
|
|
1307
|
-
const
|
|
1307
|
+
const He = async () => {
|
|
1308
1308
|
if (!R) return;
|
|
1309
1309
|
if (!$ && !I) {
|
|
1310
1310
|
S(!0);
|
|
@@ -1312,7 +1312,7 @@ function ra() {
|
|
|
1312
1312
|
}
|
|
1313
1313
|
if (!$) {
|
|
1314
1314
|
const T = await ke(R), Y = y.getState(), M = Y.portrait, Z = Y.voucherConfig.templateHue;
|
|
1315
|
-
let X = await
|
|
1315
|
+
let X = await $e(T, R, M.bgOpacity, M.bgBlur);
|
|
1316
1316
|
M.engravingIntensity > 0 && (X = await re(X, M.engravingIntensity, Z)), n(X);
|
|
1317
1317
|
} else {
|
|
1318
1318
|
i(!1, null);
|
|
@@ -1325,10 +1325,10 @@ function ra() {
|
|
|
1325
1325
|
}
|
|
1326
1326
|
}, ve = (f) => {
|
|
1327
1327
|
l(f), D.current && clearTimeout(D.current), R && (D.current = setTimeout(oe, 150));
|
|
1328
|
-
},
|
|
1328
|
+
}, Ue = async (f) => {
|
|
1329
1329
|
if (d(f), !R) return;
|
|
1330
1330
|
const T = await ke(R), Y = y.getState(), M = Y.portrait, Z = Y.voucherConfig.templateHue;
|
|
1331
|
-
let X = await
|
|
1331
|
+
let X = await $e(T, R, M.bgOpacity, M.bgBlur);
|
|
1332
1332
|
M.engravingIntensity > 0 && (X = await re(X, M.engravingIntensity, Z)), n(X);
|
|
1333
1333
|
}, Te = (f) => {
|
|
1334
1334
|
s(f), A.current && clearTimeout(A.current), !(!R || !N) && (A.current = setTimeout(oe, 150));
|
|
@@ -1448,7 +1448,7 @@ function ra() {
|
|
|
1448
1448
|
"button",
|
|
1449
1449
|
{
|
|
1450
1450
|
className: "btn btn-ghost btn gap-2 text-base-content/70",
|
|
1451
|
-
onClick:
|
|
1451
|
+
onClick: He,
|
|
1452
1452
|
disabled: g || !R,
|
|
1453
1453
|
children: [
|
|
1454
1454
|
/* @__PURE__ */ v("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
|
|
@@ -1515,11 +1515,11 @@ function ra() {
|
|
|
1515
1515
|
}
|
|
1516
1516
|
),
|
|
1517
1517
|
/* @__PURE__ */ u(
|
|
1518
|
-
|
|
1518
|
+
Nn,
|
|
1519
1519
|
{
|
|
1520
1520
|
isOpen: L,
|
|
1521
1521
|
onClose: () => S(!1),
|
|
1522
|
-
onSubmit:
|
|
1522
|
+
onSubmit: Ue
|
|
1523
1523
|
}
|
|
1524
1524
|
)
|
|
1525
1525
|
] });
|
|
@@ -1646,7 +1646,7 @@ function Lt(e) {
|
|
|
1646
1646
|
return et;
|
|
1647
1647
|
}
|
|
1648
1648
|
const Ze = 0.75;
|
|
1649
|
-
function
|
|
1649
|
+
function Bn(e) {
|
|
1650
1650
|
const t = Lt(), n = Ze, a = (r) => ({
|
|
1651
1651
|
portrait: {
|
|
1652
1652
|
x: r.portrait.x * n,
|
|
@@ -1691,7 +1691,7 @@ function Nn(e) {
|
|
|
1691
1691
|
back: a(t.back)
|
|
1692
1692
|
};
|
|
1693
1693
|
}
|
|
1694
|
-
function
|
|
1694
|
+
function Cn(e, t) {
|
|
1695
1695
|
const n = St();
|
|
1696
1696
|
return {
|
|
1697
1697
|
...n,
|
|
@@ -1699,7 +1699,7 @@ function Bn(e, t) {
|
|
|
1699
1699
|
height: Math.round(n.height * Ze)
|
|
1700
1700
|
};
|
|
1701
1701
|
}
|
|
1702
|
-
function
|
|
1702
|
+
function An(e, t) {
|
|
1703
1703
|
const [n, a] = H(e);
|
|
1704
1704
|
return j(() => {
|
|
1705
1705
|
const r = setTimeout(() => a(e), t);
|
|
@@ -1707,7 +1707,7 @@ function Cn(e, t) {
|
|
|
1707
1707
|
}, [e, t]), n;
|
|
1708
1708
|
}
|
|
1709
1709
|
function ia({ onPortraitClick: e, onFileDrop: t } = {}) {
|
|
1710
|
-
const n = y((b) => b.appLanguage), a = y((b) => b.voucherConfig.language), r = y((b) => b.voucherConfig.hours), c = y((b) => b.voucherConfig.description), i = y((b) => b.voucherConfig.templateHue), s = y((b) => b.personalInfo), o = y((b) => b.portrait), l = y((b) => b.currentSide), m = y((b) => b.flipSide), p = y((b) => b.setPortraitPan), h =
|
|
1710
|
+
const n = y((b) => b.appLanguage), a = y((b) => b.voucherConfig.language), r = y((b) => b.voucherConfig.hours), c = y((b) => b.voucherConfig.description), i = y((b) => b.voucherConfig.templateHue), s = y((b) => b.personalInfo), o = y((b) => b.portrait), l = y((b) => b.currentSide), m = y((b) => b.flipSide), p = y((b) => b.setPortraitPan), h = An(i, 150), g = ue(n), w = W(null), I = W(null), d = W(null), [k, E] = H(!1), [x, P] = H(!1), [L, S] = H(!1), [D, A] = H(!1), R = W(null), N = W(null), $ = W(!1), ee = W(0), U = Cn(), _ = Bn(), te = o.useEnhanced && o.enhanced ? o.enhanced : o.original, ie = Tt(a, r, c), [ne, we] = H(""), [q, ae] = H(""), [J, ye] = H(""), [re, ke] = H(""), [oe, He] = H(""), [ve, Ue] = H(""), [Te, Ee] = H(!0);
|
|
1711
1711
|
j(() => {
|
|
1712
1712
|
let b = !0;
|
|
1713
1713
|
Ee(!0);
|
|
@@ -1716,13 +1716,13 @@ function ia({ onPortraitClick: e, onFileDrop: t } = {}) {
|
|
|
1716
1716
|
ct(r, a, "front"),
|
|
1717
1717
|
ct(r, a, "back")
|
|
1718
1718
|
]);
|
|
1719
|
-
b && (we(z.background), ae(z.badges), ye(z.frame), ke(V.background),
|
|
1719
|
+
b && (we(z.background), ae(z.badges), ye(z.frame), ke(V.background), He(V.badges), Ue(V.frame), Ee(!1));
|
|
1720
1720
|
}
|
|
1721
1721
|
return B(), () => {
|
|
1722
1722
|
b = !1;
|
|
1723
1723
|
};
|
|
1724
1724
|
}, [r, a]), j(() => {
|
|
1725
|
-
!w.current || !ne || !q || !J ||
|
|
1725
|
+
!w.current || !ne || !q || !J || ln(
|
|
1726
1726
|
w.current,
|
|
1727
1727
|
ne,
|
|
1728
1728
|
q,
|
|
@@ -1740,7 +1740,7 @@ function ia({ onPortraitClick: e, onFileDrop: t } = {}) {
|
|
|
1740
1740
|
a
|
|
1741
1741
|
);
|
|
1742
1742
|
}, [U, ne, q, J, te, s.name, _, o.zoom, o.panX, o.panY, h, r, a]), j(() => {
|
|
1743
|
-
!I.current || !re || !oe || !ve ||
|
|
1743
|
+
!I.current || !re || !oe || !ve || dn(
|
|
1744
1744
|
I.current,
|
|
1745
1745
|
re,
|
|
1746
1746
|
oe,
|
|
@@ -1765,7 +1765,7 @@ function ia({ onPortraitClick: e, onFileDrop: t } = {}) {
|
|
|
1765
1765
|
}, [l]);
|
|
1766
1766
|
const T = O((b, B) => {
|
|
1767
1767
|
if (!d.current || l !== "front") return !1;
|
|
1768
|
-
const z = d.current.getBoundingClientRect(), V = z.width / U.width,
|
|
1768
|
+
const z = d.current.getBoundingClientRect(), V = z.width / U.width, Oe = z.height / U.height, Pe = (b - z.left) / V, Ye = (B - z.top) / Oe, { x: We, y: ze, radiusX: _e, radiusY: Ot } = _.front.portrait, at = (Pe - We) / _e, rt = (Ye - ze) / Ot;
|
|
1769
1769
|
return at * at + rt * rt <= 1;
|
|
1770
1770
|
}, [l, U.width, U.height, _.front.portrait]), Y = 5, M = O((b, B) => {
|
|
1771
1771
|
o.original && (P(!0), R.current = {
|
|
@@ -1779,8 +1779,8 @@ function ia({ onPortraitClick: e, onFileDrop: t } = {}) {
|
|
|
1779
1779
|
const z = performance.now();
|
|
1780
1780
|
if (z - ee.current < 33) return;
|
|
1781
1781
|
ee.current = z;
|
|
1782
|
-
const V = d.current.getBoundingClientRect(), Pe = 4 / Math.max(V.width, V.height) * o.zoom,
|
|
1783
|
-
p(
|
|
1782
|
+
const V = d.current.getBoundingClientRect(), Pe = 4 / Math.max(V.width, V.height) * o.zoom, Ye = (b - R.current.x) * Pe, We = (B - R.current.y) * Pe, ze = Math.max(-1, Math.min(1, R.current.panX + Ye)), _e = Math.max(-1, Math.min(1, R.current.panY + We));
|
|
1783
|
+
p(ze, _e);
|
|
1784
1784
|
}, [x, p, o.zoom]), X = O(() => {
|
|
1785
1785
|
P(!1), R.current = null, N.current = null;
|
|
1786
1786
|
}, []), tt = O(() => {
|
|
@@ -1981,7 +1981,7 @@ function sa() {
|
|
|
1981
1981
|
const e = W(null), t = W(null);
|
|
1982
1982
|
return { frontCanvasRef: e, backCanvasRef: t };
|
|
1983
1983
|
}
|
|
1984
|
-
const
|
|
1984
|
+
const Mn = `
|
|
1985
1985
|
// Translations for banner text
|
|
1986
1986
|
const TRANSLATIONS = {
|
|
1987
1987
|
de: {
|
|
@@ -2458,9 +2458,9 @@ self.onmessage = async (e) => {
|
|
|
2458
2458
|
};
|
|
2459
2459
|
`;
|
|
2460
2460
|
let Ge = null, ut = null;
|
|
2461
|
-
function
|
|
2461
|
+
function Dn() {
|
|
2462
2462
|
if (!Ge) {
|
|
2463
|
-
const e = new Blob([
|
|
2463
|
+
const e = new Blob([Mn], { type: "application/javascript" });
|
|
2464
2464
|
ut = URL.createObjectURL(e), Ge = new Worker(ut, { type: "module" });
|
|
2465
2465
|
}
|
|
2466
2466
|
return Ge;
|
|
@@ -2476,7 +2476,7 @@ function gt(e, t) {
|
|
|
2476
2476
|
a += String.fromCharCode(n[r]);
|
|
2477
2477
|
return `data:${t};base64,${btoa(a)}`;
|
|
2478
2478
|
}
|
|
2479
|
-
async function
|
|
2479
|
+
async function Hn(e) {
|
|
2480
2480
|
const {
|
|
2481
2481
|
frontTemplateSrc: t,
|
|
2482
2482
|
backTemplateSrc: n,
|
|
@@ -2500,7 +2500,7 @@ async function Dn(e) {
|
|
|
2500
2500
|
]);
|
|
2501
2501
|
let x = null;
|
|
2502
2502
|
return i && (x = await Ve(i)), new Promise((P, L) => {
|
|
2503
|
-
const S =
|
|
2503
|
+
const S = Dn(), D = setTimeout(() => {
|
|
2504
2504
|
S.removeEventListener("message", A), S.removeEventListener("error", R), URL.revokeObjectURL(k), URL.revokeObjectURL(E), x && URL.revokeObjectURL(x), L(new Error("PDF generation timed out. Please try again."));
|
|
2505
2505
|
}, 6e4), A = (N) => {
|
|
2506
2506
|
if (clearTimeout(D), S.removeEventListener("message", A), S.removeEventListener("error", R), URL.revokeObjectURL(k), URL.revokeObjectURL(E), x && URL.revokeObjectURL(x), N.data.type === "success")
|
|
@@ -2558,13 +2558,13 @@ async function Dn(e) {
|
|
|
2558
2558
|
});
|
|
2559
2559
|
});
|
|
2560
2560
|
}
|
|
2561
|
-
function
|
|
2561
|
+
function Un(e, t) {
|
|
2562
2562
|
const n = URL.createObjectURL(e), a = document.createElement("a");
|
|
2563
2563
|
a.href = n, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), URL.revokeObjectURL(n);
|
|
2564
2564
|
}
|
|
2565
|
-
async function
|
|
2566
|
-
const t = await
|
|
2567
|
-
|
|
2565
|
+
async function On(e) {
|
|
2566
|
+
const t = await Hn(e);
|
|
2567
|
+
Un(t, e.filename);
|
|
2568
2568
|
}
|
|
2569
2569
|
function ca() {
|
|
2570
2570
|
const e = y((d) => d.appLanguage), t = y((d) => d.voucherConfig.language), n = y((d) => d.voucherConfig.hours), a = y((d) => d.voucherConfig.description), r = y((d) => d.voucherConfig.templateHue), c = y((d) => d.personalInfo), i = y((d) => d.portrait), s = y((d) => d.isExporting), o = y((d) => d.setIsExporting), l = ue(e), m = St(), p = Lt(), h = i.useEnhanced && i.enhanced ? i.enhanced : i.original, g = Tt(t, n, a), w = c.name.trim().length > 0 && c.email.trim().length > 0 && c.phone.trim().length > 0 && i.original !== null;
|
|
@@ -2580,7 +2580,7 @@ function ca() {
|
|
|
2580
2580
|
st(n, t, "front"),
|
|
2581
2581
|
st(n, t, "back")
|
|
2582
2582
|
]), E = `zeitgutschein-${n}h-${c.name.replace(/\s+/g, "-").toLowerCase()}.pdf`;
|
|
2583
|
-
await
|
|
2583
|
+
await On({
|
|
2584
2584
|
frontTemplateSrc: d,
|
|
2585
2585
|
backTemplateSrc: k,
|
|
2586
2586
|
templateWidth: m.width,
|
|
@@ -2633,7 +2633,7 @@ function ca() {
|
|
|
2633
2633
|
}
|
|
2634
2634
|
);
|
|
2635
2635
|
}
|
|
2636
|
-
function
|
|
2636
|
+
function Yn() {
|
|
2637
2637
|
const e = y((a) => a.appLanguage), t = y((a) => a.setAppLanguage), n = (a) => {
|
|
2638
2638
|
t(a);
|
|
2639
2639
|
};
|
|
@@ -2661,17 +2661,17 @@ function la() {
|
|
|
2661
2661
|
return /* @__PURE__ */ v("div", { className: "navbar bg-currency-green text-currency-cream shadow-lg shrink-0", children: [
|
|
2662
2662
|
/* @__PURE__ */ u("div", { className: "navbar-start", children: /* @__PURE__ */ u("a", { className: "btn btn-ghost text-xl font-currency font-bold", children: t.header.title }) }),
|
|
2663
2663
|
/* @__PURE__ */ u("div", { className: "navbar-center hidden sm:flex", children: /* @__PURE__ */ u("span", { className: "text-sm opacity-80", children: t.header.subtitle }) }),
|
|
2664
|
-
/* @__PURE__ */ u("div", { className: "navbar-end", children: /* @__PURE__ */ u(
|
|
2664
|
+
/* @__PURE__ */ u("div", { className: "navbar-end", children: /* @__PURE__ */ u(Yn, {}) })
|
|
2665
2665
|
] });
|
|
2666
2666
|
}
|
|
2667
|
-
const
|
|
2667
|
+
const Ae = "/", Wn = {
|
|
2668
2668
|
id: "time-voucher-classic-de",
|
|
2669
2669
|
name: "Zeitgutschein Classic",
|
|
2670
2670
|
type: "time-voucher",
|
|
2671
2671
|
category: "classic",
|
|
2672
2672
|
images: {
|
|
2673
|
-
front: `${
|
|
2674
|
-
back: `${
|
|
2673
|
+
front: `${Ae}templates/front_hdpi_de.jpg`,
|
|
2674
|
+
back: `${Ae}templates/back_hdpi_de.jpg`,
|
|
2675
2675
|
width: 6144,
|
|
2676
2676
|
height: 4096
|
|
2677
2677
|
},
|
|
@@ -2728,14 +2728,14 @@ const Ce = "/", Yn = {
|
|
|
2728
2728
|
}
|
|
2729
2729
|
},
|
|
2730
2730
|
languages: ["de"]
|
|
2731
|
-
},
|
|
2731
|
+
}, zn = {
|
|
2732
2732
|
id: "time-voucher-classic-en",
|
|
2733
2733
|
name: "Time Voucher Classic",
|
|
2734
2734
|
type: "time-voucher",
|
|
2735
2735
|
category: "classic",
|
|
2736
2736
|
images: {
|
|
2737
|
-
front: `${
|
|
2738
|
-
back: `${
|
|
2737
|
+
front: `${Ae}templates/front_ldpi_en.png`,
|
|
2738
|
+
back: `${Ae}templates/back_ldpi_en.png`,
|
|
2739
2739
|
width: 1536,
|
|
2740
2740
|
height: 1024
|
|
2741
2741
|
},
|
|
@@ -2793,9 +2793,9 @@ const Ce = "/", Yn = {
|
|
|
2793
2793
|
},
|
|
2794
2794
|
languages: ["en"]
|
|
2795
2795
|
}, mt = [
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
],
|
|
2796
|
+
Wn,
|
|
2797
|
+
zn
|
|
2798
|
+
], _n = {
|
|
2799
2799
|
async listTemplates(e) {
|
|
2800
2800
|
let t = [...mt];
|
|
2801
2801
|
return e != null && e.type && (t = t.filter((n) => n.type === e.type)), e != null && e.category && (t = t.filter((n) => n.category === e.category)), e != null && e.language && (t = t.filter((n) => n.languages.includes(e.language))), t;
|
|
@@ -2810,29 +2810,29 @@ const Ce = "/", Yn = {
|
|
|
2810
2810
|
function da(e) {
|
|
2811
2811
|
return e === "de" ? "time-voucher-classic-de" : "time-voucher-classic-en";
|
|
2812
2812
|
}
|
|
2813
|
-
let
|
|
2813
|
+
let De = _n;
|
|
2814
2814
|
function ua(e) {
|
|
2815
|
-
|
|
2815
|
+
De = e;
|
|
2816
2816
|
}
|
|
2817
2817
|
function ga() {
|
|
2818
|
-
return
|
|
2818
|
+
return De;
|
|
2819
2819
|
}
|
|
2820
2820
|
async function ma(e) {
|
|
2821
|
-
return
|
|
2821
|
+
return De.listTemplates(e);
|
|
2822
2822
|
}
|
|
2823
2823
|
async function ha(e) {
|
|
2824
|
-
return
|
|
2824
|
+
return De.getTemplate(e);
|
|
2825
2825
|
}
|
|
2826
2826
|
export {
|
|
2827
|
-
|
|
2827
|
+
Nn as ApiKeyModal,
|
|
2828
2828
|
ia as BillPreview,
|
|
2829
2829
|
ca as ExportButton,
|
|
2830
2830
|
la as Header,
|
|
2831
2831
|
xe as LAYOUT_HDPI,
|
|
2832
2832
|
Ie as LAYOUT_LDPI,
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2833
|
+
Yn as LanguageToggle,
|
|
2834
|
+
Fn as PREVIEW_HEIGHT,
|
|
2835
|
+
Kn as PREVIEW_WIDTH,
|
|
2836
2836
|
Qn as PersonalInfoForm,
|
|
2837
2837
|
ra as PortraitUpload,
|
|
2838
2838
|
de as TEMPLATE_HEIGHT,
|
|
@@ -2842,27 +2842,27 @@ export {
|
|
|
2842
2842
|
oa as VoucherConfig,
|
|
2843
2843
|
jt as applyEngravingEffect,
|
|
2844
2844
|
Ft as applyHueShift,
|
|
2845
|
-
|
|
2846
|
-
|
|
2845
|
+
Qt as clearCompositorCache,
|
|
2846
|
+
en as clearHueShiftedCache,
|
|
2847
2847
|
Jt as composeTemplate,
|
|
2848
2848
|
st as composeTemplateFullRes,
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2849
|
+
Un as downloadBlob,
|
|
2850
|
+
sn as drawContactInfo,
|
|
2851
|
+
on as drawMultilineText,
|
|
2852
|
+
rn as drawOvalPortrait,
|
|
2853
2853
|
pe as drawTemplate,
|
|
2854
2854
|
kt as drawText,
|
|
2855
2855
|
aa as enhancePortrait,
|
|
2856
|
-
|
|
2856
|
+
On as exportBillAsPDF,
|
|
2857
2857
|
Tt as formatDescription,
|
|
2858
|
-
|
|
2858
|
+
Hn as generateBillPDF,
|
|
2859
2859
|
Qe as getApiKey,
|
|
2860
2860
|
da as getDefaultTemplateId,
|
|
2861
2861
|
Lt as getLayout,
|
|
2862
2862
|
ta as getRemoveBackgroundEndpoint,
|
|
2863
2863
|
St as getTemplate,
|
|
2864
2864
|
ha as getTemplateById,
|
|
2865
|
-
|
|
2865
|
+
Zn as getTemplateDimensions,
|
|
2866
2866
|
ct as getTemplateLayers,
|
|
2867
2867
|
ga as getTemplateProvider,
|
|
2868
2868
|
je as hasApiKey,
|
|
@@ -2870,15 +2870,15 @@ export {
|
|
|
2870
2870
|
ma as listTemplates,
|
|
2871
2871
|
C as loadImage,
|
|
2872
2872
|
Jn as preloadAllTemplates,
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2873
|
+
qn as preloadBaseImages,
|
|
2874
|
+
Ln as removeBackground,
|
|
2875
|
+
dn as renderBackSide,
|
|
2876
|
+
ln as renderFrontSide,
|
|
2877
2877
|
Xt as resizeImage,
|
|
2878
|
-
|
|
2878
|
+
Sn as setApiKey,
|
|
2879
2879
|
ea as setRemoveBackgroundEndpoint,
|
|
2880
2880
|
ua as setTemplateProvider,
|
|
2881
|
-
|
|
2881
|
+
_n as staticTemplateProvider,
|
|
2882
2882
|
ue as t,
|
|
2883
2883
|
sa as useBillCanvasRefs,
|
|
2884
2884
|
y as useBillStore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antontranelis/money-printer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.85",
|
|
4
4
|
"description": "Create personalized time vouchers that look like real currency. React components for voucher generation with PDF export.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|