Files
boc/backups/2026-07-12-1023/landvex-prod/assets/MissionDetail-C7kUviJC.js
T

18 lines
48 KiB
JavaScript
Raw Normal View History

import{o as Se,r as l,a as ie,u as Te,j as e,x as vs,y as ys,v as T,z as U,q as G,C as O,S as xe,X as $e,w as h,L as A,A as X,i as $,V as ws,D as ks,E as Ee,F as Ds,G as _s,H as Ie,W as As,e as Cs,J as Ss,d as Ts,K as $s,N as Es,O as Is,Q as Re,Y as Rs,Z as Ms,_ as Me,$ as Os,a0 as Ps,p as Vs,a1 as Ls,a2 as Fs,k as zs,a3 as Us,a4 as Gs,a5 as Js,T as we,b as Bs,M as oe,f as te,a6 as Hs,a7 as ae,B as Ks,a8 as ce}from"./index-oAPVDf-r.js";import{u as qs}from"./useMissionExamples-B0el-PHm.js";import{A as Ys,u as Xs}from"./useIdentityVerification-CD3mPBIt.js";import{C as Qs}from"./circle-check-D3hjqUcb.js";import{S as Ws}from"./SecureCamera-mAkOb0O2.js";import{A as ke}from"./award-By-NEFpe.js";import{T as Zs}from"./triangle-alert-B87swlNS.js";import{C as et}from"./check-CG8zylH4.js";import{A as De}from"./index-B-MEeiYV.js";import{S as st}from"./shield-BWGzcrms.js";import{G as tt}from"./gift-lxeNwCUB.js";import{T as at}from"./ticket-D1bxyCST.js";import{E as rt}from"./external-link-C86N9iPS.js";import{A as _e}from"./arrow-left-m6EiMbb-.js";import{C as Ae}from"./circle-alert-C1Hs9zwh.js";import{C as de}from"./clock-DRtqJZUo.js";import{I as it}from"./image-DuU1QaV8.js";import{T as Ce}from"./timer-C5oB41EC.js";import{R as nt}from"./refresh-cw-DEBvxUr1.js";/**
* @license lucide-react v0.462.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const lt=Se("FlaskConical",[["path",{d:"M10 2v7.527a2 2 0 0 1-.211.896L4.72 20.55a1 1 0 0 0 .9 1.45h12.76a1 1 0 0 0 .9-1.45l-5.069-10.127A2 2 0 0 1 14 9.527V2",key:"pzvekw"}],["path",{d:"M8.5 2h7",key:"csnxdl"}],["path",{d:"M7 16h10",key:"wp8him"}]]);/**
* @license lucide-react v0.462.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const ot=Se("ShieldAlert",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}],["path",{d:"M12 8v4",key:"1got3b"}],["path",{d:"M12 16h.01",key:"1drbdi"}]]);function ct(s,a,r){if(!s)return{title:r("missionDetail.verifyForMissions"),description:r("missionDetail.verifyDescription")};const n=["IAL1","IAL2","IAL3"],i=n.indexOf(s),c=n.indexOf(a??"IAL2");if(i<c){if(s==="IAL1"&&(a==="IAL2"||a==="IAL3"))return{title:"Förhöjd verifiering krävs",description:"Detta uppdrag kräver förhöjd verifiering (ID-handling). Verifiera din identitet för att ta uppdraget."};if(s==="IAL2"&&a==="IAL3")return{title:"Fullständig verifiering krävs",description:"Detta uppdrag kräver fullständig identitetsverifiering (IAL3). Kontakta support för att uppgradera."}}return{title:r("missionDetail.verifyForMissions"),description:r("missionDetail.verifyDescription")}}const Oe=l.forwardRef(({title:s,description:a,achievedIAL:r,requiredIAL:n},i)=>{const{t:c}=ie(),o=Te(),{title:j,description:t}=ct(r,n,c),p=s||j,g=a||t,v=r!=null&&n!=null&&r!==n;return e.jsx(vs,{ref:i,className:"border-primary/30 bg-primary/5",children:e.jsxs(ys,{className:"p-6 text-center space-y-4",children:[e.jsx("div",{className:"w-16 h-16 rounded-full bg-primary/20 flex items-center justify-center mx-auto",children:v?e.jsx(ot,{className:"w-8 h-8 text-primary"}):e.jsx(Qs,{className:"w-8 h-8 text-primary"})}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h2",{className:"text-lg font-semibold text-foreground",children:p}),e.jsx("p",{className:"text-sm text-muted-foreground",children:g}),r&&n&&e.jsxs("p",{className:"text-xs text-muted-foreground/70",children:["Nuvarande nivå: ",r," · Krävs: ",n]})]}),e.jsxs(T,{onClick:()=>o("/verify-identity?returnTo="+encodeURIComponent(window.location.pathname)),className:"w-full",children:[v?"Uppgradera verifiering":c("missionDetail.verifyForMissions"),e.jsx(Ys,{className:"w-4 h-4 ml-2"})]})]})})});Oe.displayName="VerificationRequired";const dt=()=>{const[s,a]=l.useState(!1),[r,n]=l.useState(null),[i,c]=l.useState(null),o=l.useCallback(async t=>{a(!0),c(null),n(null);try{const p=t.replace(/^data:image\/\w+;base64,/,""),{data:g,error:v}=await U.functions.invoke("validate-aesthetic",{body:{imageBase64:p,missionType:"certified_global"}});if(v)throw new Error(v.message);if(!(g!=null&&g.success)||!(g!=null&&g.validation))throw new Error((g==null?void 0:g.error)||"Validation failed");return n(g.validation),g.validation}catch(p){const g=p instanceof Error?p.message:"Kunde inte validera bild";return c(g),console.error("Aesthetic validation error:",p),null}finally{a(!1)}},[]),j=l.useCallback(()=>{n(null),c(null)},[]);return{validateImage:o,isValidating:s,validationResult:r,error:i,reset:j}},me=({score:s,label:a,color:r})=>e.jsxs("div",{className:"space-y-1",children:[e.jsxs("div",{className:"flex justify-between text-xs",children:[e.jsx("span",{className:"text-muted-foreground",children:a}),e.jsxs("span",{className:"font-medium",children:[s,"/100"]})]}),e.jsx("div",{className:"h-2 bg-muted rounded-full overflow-hidden",children:e.jsx(G.div,{initial:{width:0},animate:{width:`${s}%`},transition:{duration:.8,ease:"easeOut"},className:`h-full rounded-full ${r}`})})]}),re=({passed:s,label:a})=>e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[s?e.jsx(et,{className:"w-4 h-4 text-green-500"}):e.jsx($e,{className:"w-4 h-4 text-red-500"}),e.jsx("span",{className:s?"text-foreground":"text-muted-foreground",children:a})]}),mt=({result:s,compact:a=!1})=>{const{t:r}=ie(),n=o=>o>=80?"bg-gradient-to-r from-green-500 to-emerald-400":o>=60?"bg-gradient-to-r from-yellow-500 to-amber-400":"bg-gradient-to-r from-red-500 to-orange-400",c=(o=>o>=90?{grade:"A+",text:r("aesthetic.gradeExceptional"),emoji:"🏆"}:o>=80?{grade:"A",text:r("aesthetic.gradeExcellent"),emoji:"⭐"}:o>=70?{grade:"B",text:r("aesthetic.gradeGood"),emoji:"👍"}:o>=60?{grade:"C",text:r("aesthetic.gradeAccepted"),emoji:"👌"}:{grade:"D",t
You can add a description to the \`${J}\` by passing a \`${Je}\` component as a child, which also benefits sighted users by adding visible context to the dialog.
Alternatively, you can use your own component as a description by assigning it an \`id\` and passing the same value to the \`aria-describedby\` prop in \`${J}\`. If the description is confusing or duplicative for sighted users, you can use the \`@radix-ui/react-visually-hidden\` primitive as a wrapper around your description component.
For more information, see https://radix-ui.com/primitives/docs/components/alert-dialog`;return l.useEffect(()=>{var n;document.getElementById((n=s.current)==null?void 0:n.getAttribute("aria-describedby"))||console.warn(a)},[a,s]),null},_t=Ve,At=Le,Ye=Fe,Xe=ze,Qe=He,We=qe,Ze=Ge,es=Be;const Ct=_t,St=At,ss=l.forwardRef(({className:s,...a},r)=>e.jsx(Ye,{className:$("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",s),...a,ref:r}));ss.displayName=Ye.displayName;const ts=l.forwardRef(({className:s,...a},r)=>e.jsxs(St,{children:[e.jsx(ss,{}),e.jsx(Xe,{ref:r,className:$("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",s),...a})]}));ts.displayName=Xe.displayName;const as=({className:s,...a})=>e.jsx("div",{className:$("flex flex-col space-y-2 text-center sm:text-left",s),...a});as.displayName="AlertDialogHeader";const rs=({className:s,...a})=>e.jsx("div",{className:$("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",s),...a});rs.displayName="AlertDialogFooter";const is=l.forwardRef(({className:s,...a},r)=>e.jsx(Ze,{ref:r,className:$("text-lg font-semibold",s),...a}));is.displayName=Ze.displayName;const ns=l.forwardRef(({className:s,...a},r)=>e.jsx(es,{ref:r,className:$("text-sm text-muted-foreground",s),...a}));ns.displayName=es.displayName;const ls=l.forwardRef(({className:s,...a},r)=>e.jsx(Qe,{ref:r,className:$(Me(),s),...a}));ls.displayName=Qe.displayName;const os=l.forwardRef(({className:s,...a},r)=>e.jsx(We,{ref:r,className:$(Me({variant:"outline"}),"mt-2 sm:mt-0",s),...a}));os.displayName=We.displayName;const Yt=()=>{var be,Ne,ve;const{t:s}=ie(),{id:a}=Os(),r=Te(),n=Ps(),{user:i}=Vs();Ls();const{isVerified:c,achievedIAL:o,checkStatus:j}=Xs(i==null?void 0:i.id),{mission:t,loading:p,error:g}=Fs(a),{goodExamples:v,badExamples:y,hasExamples:Q,loading:W}=qs(a),{latitude:Z,longitude:ee,loading:ne}=zs(),[L,I]=l.useState(!1),[d,b]=l.useState(!1),[x,u]=l.useState(null),[w,D]=l.useState(!0),[R,F]=l.useState(null),[B,se]=l.useState(!1),[C,ue]=l.useState(!1),[H,pe]=l.useState(!1),[cs,K]=l.useState(null),[le,q]=l.useState(!1),[ds,ge]=l.useState(!1),[ms,xs]=l.useState(!1),P=Us({enabled:ms,autoNavigate:!1}),fe=l.useCallback(()=>{try{const m=new(window.AudioContext||window.webkitAudioContext),f=(_,z)=>{const k=m.createOscillator(),S=m.createGain();k.connect(S),S.connect(m.destination),k.frequency.value=z,k.type="sine",S.gain.setValueAtTime(.3,_),S.gain.exponentialRampToValueAtTime(.01,_+.15),k.start(_),k.stop(_+.15)},N=m.currentTime;f(N,800),f(N+.2,1e3),f(N+.4,1200)}catch(m){console.log("Could not play warning sound:",m)}},[]),he=l.useCallback(()=>{window.history.length>2?r(-1):r("/")},[r]),je=(be=t==null?void 0:t.title)==null?void 0:be.toLowerCase().includes("busskur");l.useEffect(()=>{(async()=>{if(!i||!a){D(!1);return}const f=ce.getToken();if(!f){D(!1);return}try{const N=await fetch(`https://api.quixzoom.com/api/qz/missions/claims/active?mission_id=${encodeURIComponent(a)}`,{headers:{Authorization:`Bearer ${f}`}});if(N.ok){const _=await N.json();_.claim&&u(_.claim)}}catch(N){console.error("[MissionDetail] fetchActiveClaim error:",N)}D(!1)})()},[i,a]),l.useEffect(()=>{i!=null&&i.id&&j()},[i==null?void 0:i.id,j]),l.useEffect(()=>{i!=null&&i.id&&j()},[n.key]),l.useEffect(()=>{if(!(x!=null&&x.expires_at)){F(null),se(!1);return}const m=()=>{const N=new Date,z=new Date(x.expires_at).getTime()-N.getTime();if(z<=0){F("Utgången"),ue(!1),h.error("Tiden har gått ut!",{description:"Uppdraget har släppts automatiskt."}),u(null);return}const k=Math.floor(z/6e4),S=Math.floor(z%6e4/