PageSourceSearch

https://genaix.org/assets/DigitalPassport-iNjvuIxy.js

js genaix.org collected 2026-10-07 22:20:30 UTC 33,585 bytes, 261 lines download raw bytes

1import{p as W,r as b,j as e,C as u,c as P,e as C,q as S,a as g,$ as Z,f as k,v as Y,J as o,aW as G,s as N,R as T,F as O,B as w,A as $,T as V,O as J,w as Q,S as F,b as M,U as X}from"./index-nbQLPUsP.js";import{T as ee,a as se,b as A,c as L}from"./tabs-DIsTv2CL.js";import{B}from"./BlockchainCredentialViewer-BS7WJMuW.js";import{S as ae}from"./SEOHead-PD39hXX2.js";import{U as te}from"./upload-DdhiZ2LJ.js";import{L as I}from"./loader-circle-BALS4HTy.js";import{P as re}from"./progress-CDasyQJe.js";import{A as z,a as R}from"./alert-BFgNIA8U.js";import{T as q}from"./trending-down-D0gJvMtK.js";import{C as H}from"./clock-kZzggmxd.js";import{Z as K}from"./zap-BNo1Lq--.js";import{a as ie}from"./html2pdf-DQcv4CxK.js";import{D as le}from"./download-Bq94dB4z.js";import{S as ne}from"./share-2-COiVAN0Q.js";import{G as U}from"./graduation-cap-D0XaxbnU.js";import"./external-link-CebresAU.js";/**
2 * @license lucide-react v0.462.0 - ISC
3 *
4 * This source code is licensed under the ISC license.
5 * See the LICENSE file in the root directory of this source tree.
6 */const ce=W("Building",[["rect",{width:"16",height:"20",x:"4",y:"2",rx:"2",ry:"2",key:"76otgf"}],["path",{d:"M9 22v-4h6v4",key:"r93iot"}],["path",{d:"M8 6h.01",key:"1dz90k"}],["path",{d:"M16 6h.01",key:"1x0f13"}],["path",{d:"M12 6h.01",key:"1vi96p"}],["path",{d:"M12 10h.01",key:"1nrarc"}],["path",{d:"M12 14h.01",key:"1etili"}],["path",{d:"M16 10h.01",key:"1m94wz"}],["path",{d:"M16 14h.01",key:"1gbofw"}],["path",{d:"M8 10h.01",key:"19clt8"}],["path",{d:"M8 14h.01",key:"6423bh"}]]);function de({userId:i,onComplete:c}){const[m,y]=b.useState(!1),[f,l]=b.useState(!1),[x,j]=b.useState(null),a=t=>{var n;const r=(n=t.target.files)==null?void 0:n[0];if(r){if(r.type!=="application/pdf"){o.error("Please upload a PDF file");return}if(r.size>20*1024*1024){o.error("File size must be less than 20MB");return}j(r)}},h=async()=>{var t,r;if(x){y(!0);try{const n=G(i),v=`${n}/${Date.now()}_${x.name}`,{error:d}=await N.storage.from("resumes").upload(v,x,{cacheControl:"3600",upsert:!1});if(d)throw console.error("Storage upload error:",d),new Error(`Storage error: ${d.message}`);o.success("Resume uploaded! Parsing with AI..."),y(!1),l(!0);const{data:s,error:p}=await N.functions.invoke("parse-resume",{body:{resumeUrl:v,userId:n}});if(console.log("Parse resume response:",{data:s,error:p}),p){console.error("Parse resume function error:",p),l(!1),(t=p.message)!=null&&t.includes("credits")?o.error("AI Credits Exhausted",{description:"Please add credits to your workspace in Settings > Usage"}):(r=p.message)!=null&&r.includes("violates row-level security")?o.error("Permission error",{description:"Database access denied. Please contact support."}):o.error("Failed to parse resume",{description:p.message||"Unknown error occurred"});return}if(l(!1),s!=null&&s.success){const{totalSkills:D,totalEducation:_,totalEmployment:E}=s.summary;D+_+E>0?(o.success("Resume processed successfully! 🎉",{description:`Created ${D} skills, ${_} education, ${E} employment credentials`}),c()):o.warning("Resume processed but no data extracted",{description:"Please check if your resume has a standard format with clear sections"})}else s!=null&&s.error?o.error("Failed to parse resume",{description:s.error}):o.error("Unexpected response from parser")}catch(n){console.error("Error uploading resume:",n),o.error("Upload failed",{description:n.message||"An unexpected error occurred"}),y(!1),l(!1)}}};return e.jsxs(u,{className:"border-2 border-dashed",children:[e.jsxs(P,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(te,{className:"w-5 h-5"}),"Upload Resume"]}),e.jsx(S,{children:"Upload your PDF resume to automatically create blockchain credentials"})]}),e.jsxs(g,{className:"space-y-4",children:[e.jsxs("div",{className:"flex flex-col items-center justify-center border-2 border-dashed border-primary/20 rounded-lg p-8 hover:border-primary/40 transition-colors",children:[e.jsx(Z,{className:"w-12 h-12 text-primary mb-4"}),e.jsxs("label",{htmlFor:"resume-upload",className:"cursor-pointer",children:[e.jsx("input",{id:"resume-upload",type:"file",accept:".pdf",onChange:a,className:"hidden",disabled:m||f}),e.jsx(k,{variant:"outline",asChild:!0,disabled:m||f,children:e.jsx("span",{children:"Choose PDF Resume"})})]}),x&&e.jsxs("p",{className:"text-sm text-muted-foreground mt-2",children:["Selected: ",x.name]})]}),x&&e.jsx(k,{onClick:h,disabled:m||f,className:"w-full",children:m?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"Uploading..."]}):f?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"mr-2 h-4 w-4 animate-spin"}),"AI Parsing Resume..."]}):e.jsxs(e.Fragment,{children:[e.jsx(Y,{className:"mr-2 h-4 w-4"}),"Parse & Create Credentials"]})}),e.jsxs("div",{className:"text-xs text-muted-foreground space-y-1",children:[e.jsx("p",{children:"• PDF files only (max 20MB)"}),e.jsx("p",{children:"• AI will extract skills, education, and employment"}),e.jsx("p",{children:"• Blockchain credentials created automatically"})]})]})]})}function oe({userId:i}){const[c,m]=b.useState([]),[y,f]=b.useState(!0);b.useEffect(()=>{l()},[i]);const l=async()=>{try{const t=G(i),{data:r,error:n}=await N.from("user_skills").select("skill_id, skills(name)").eq("user_id",t);if(n)throw n;const v=await Promise.all(r.map(async d=>{try{const{data:s}=await N.functions.invoke("ml-decay-prediction",{body:{userId:t,skillId:d.skill_id}});return s==null?void 0:s.prediction}catch(s){return console.error("Error getting prediction:",s),null}}));m(v.filter(d=>d!==null))}catch(t){console.error("Error loading decay data:",t),o.error("Failed to load skill decay analysis")}finally{f(!1)}},x=t=>{switch(t){case"excellent":return"text-green-600 bg-green-50 border-green-200";case"good":return"text-blue-600 bg-blue-50 border-blue-200";case"declining":return"text-amber-600 bg-amber-50 border-amber-200";case"critical":return"text-red-600 bg-red-50 border-red-200";default:return"text-gray-600 bg-gray-50 border-gray-200"}},j=t=>{switch(t){case"excellent":return e.jsx(V,{className:"h-4 w-4"});case"good":return e.jsx($,{className:"h-4 w-4"});case"declining":return e.jsx(q,{className:"h-4 w-4"});case"critical":return e.jsx(O,{className:"h-4 w-4"});default:return e.jsx(H,{className:"h-4 w-4"})}};if(y)return e.jsx(u,{children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-center py-8",children:[e.jsx(T,{className:"h-6 w-6 animate-spin text-primary"}),e.jsx("span",{className:"ml-2 text-muted-foreground",children:"Analyzing skill proficiency..."})]})})});const a=c.filter(t=>t.decay_status==="critical"),h=c.filter(t=>t.decay_status==="declining");return e.jsx("div",{className:"space-y-6",children:e.jsxs(u,{children:[e.jsxs(P,{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(q,{className:"h-5 w-5"}),"ML-Powered Skill Decay Analysis"]}),e.jsx(S,{children:"Real-time proficiency tracking with machine learning predictions"})]}),e.jsxs(g,{children:[a.length>0&&e.jsxs(z,{className:"mb-4 border-red-200 bg-red-50",children:[e.jsx(O,{className:"h-4 w-4 text-red-600"}),e.jsxs(R,{className:"text-red-800",children:[e.jsxs("strong",{children:[a.length," skill(s) require immediate attention."]})," ","Refresher training strongly recommended to prevent significant proficiency loss."]})]}),h.length>0&&a.length===0&&e.jsxs(z,{className:"mb-4 border-amber-200 bg-amber-50",children:[e.jsx(H,{className:"h-4 w-4 text-amber-600"}),e.jsxs(R,{className:"text-amber-800",children:[e.jsxs("strong",{children:[h.length," skill(s) showing decline."]})," ","Consider scheduling practice sessions within the next week."]})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4",children:c.map(t=>e.jsxs(u,{className:`border ${x(t.decay_status)}`,children:[e.jsx(P,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(C,{className:"text-sm font-medium",children:t.skill_name}),e.jsxs(w,{variant:"outline",className:x(t.decay_status),children:[j(t.decay_status),e.jsx("span",{className:"ml-1 capitalize",children:t.decay_status})]})]})}),e.jsxs(g,{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex justify-between text-sm mb-1",children:[e.jsx("span",{className:"text-muted-foreground",children:"Current Proficiency"}),e.jsxs("span",{className:"font-semibold",children:[Math.round(t.predicted_proficiency*100),"%"]})]}),e.jsx(re,{value:t.predicted_proficiency*100,className:"h-2"})]}),e.jsxs("div",{className:"flex justify-between text-xs text-muted-foreground",children:[e.jsx("span",{children:"Days Inactive:"}),e.jsx("span",{className:"font-medium",children:t.days_inactive})]}),t.education_bonus>0&&e.jsxs("div",{className:"flex items-center gap-1 text-xs text-green-600",children:[e.jsx($,{className:"h-3 w-3"}),e.jsxs("span",{children:["+",Math.round(t.education_bonus*100),"% degree bonus"]})]}),t.employment_bonus>0&&e.jsxs("div",{className:"flex items-center gap-1 text-xs text-blue-600",children:[e.jsx(V,{className:"h-3 w-3"}),e.jsxs("span",{children:["+",Math.round(t.employment_bonus*100),"% work experience"]})]}),e.jsxs("div",{className:"pt-2 border-t",children:[e.jsx("p",{className:"text-xs text-muted-foreground mb-2",children:t.recommendation}),t.next_refresh_in_days>0&&e.jsxs(k,{size:"sm",variant:"outline",className:"w-full",children:[e.jsx(T,{className:"h-3 w-3 mr-1"}),"Refresh in ",t.next_refresh_in_days," days"]}),t.next_refresh_in_days<=0&&e.jsxs(k,{size:"sm",variant:"default",className:"w-full",children:[e.jsx(T,{className:"h-3 w-3 mr-1"}),"Refresh Now"]})]}),e.jsxs("div",{className:"flex items-center justify-between text-xs text-muted-foreground pt-2 border-t",children:[e.jsx("span",{children:"ML Confidence:"}),e.jsxs(w,{variant:"secondary",className:"text-xs",children:[Math.round(t.confidence_level*100),"%"]})]})]})]},t.skill_id))})]})]})})}function me({userId:i}){const[c,m]=b.useState([]),[y,f]=b.useState(!1),[l,x]=b.useState(!1),[j,a]=b.useState(null),h=async()=>{var r,n,v;f(!0);try{const[d,s,p]=await Promise.all([N.from("skill_credentials").select("credential_id, holder_user_id, created_at").eq("holder_user_id",i).is("blockchain_record_id",null).limit(20),N.from("educational_degree_credentials").select("credential_id, holder_user_id, created_at").eq("holder_user_id",i).is("blockchain_record_id",null).limit(20),N.from("employment_history_credentials").select("credential_id, holder_user_id, created_at").eq("holder_user_id",i).is("blockchain_record_id",null).limit(20)]),D=[...((r=d.data)==null?void 0:r.map(_=>({..._,credential_type:"SKILL"})))||[],...((n=s.data)==null?void 0:n.map(_=>({..._,credential_type:"EDUCATION"})))||[],...((v=p.data)==null?void 0:v.map(_=>({..._,credential_type:"EMPLOYMENT"})))||[]];m(D)}catch(d){console.error("Error loading pending credentials:",d),o.error("Failed to load pending credentials")}finally{f(!1)}},t=async()=>
6{if(c.length===0){o.error("No pending credentials to process");return}x(!0),a(null);try{o.info(`Processing ${c.length} credentials in batch...`);const r=c.map(d=>({credentialId:d.credential_id,credentialType:d.credential_type,userId:d.holder_user_id})),{data:n,error:v}=await N.functions.invoke("batch-write-to-blockchain",{body:{credentials:r}});if(v)throw v;if(n.success){a(n.gasSavings),o.success(`✅ ${r.length} credentials written to blockchain!`,{description:`Gas savings: ${n.gasSavings} | Block #${n.blockNumber}`});const d=r.map(async s=>{try{await N.functions.invoke("ipfs-metadata-storage",{body:{credentialId:s.credentialId,tableName:s.credentialType==="SKILL"?"skill_credentials":s.credentialType==="EDUCATION"?"educational_degree_credentials":"employment_history_credentials",metadata:{credentialType:s.credentialType,userId:s.userId,blockchainTx:n.batchTransactionHash,merkleRoot:n.merkleRoot}}})}catch(p){console.error("IPFS upload error:",p)}});await Promise.all(d),await h()}else throw new Error(n.error||"Batch write failed")}catch(r){console.error("Batch processing error:",r),o.error("Failed to process batch")}finally{x(!1)}};return e.jsxs(u,{children:[e.jsx(P,{children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(K,{className:"h-5 w-5 text-yellow-500"}),"Batch Blockchain Writer"]}),e.jsx(S,{children:"Process multiple credentials in a single transaction (90%+ gas savings)"})]}),e.jsx(k,{onClick:h,variant:"outline",size:"sm",disabled:y,children:y?e.jsx(I,{className:"h-4 w-4 animate-spin"}):"Refresh"})]})}),e.jsxs(g,{className:"space-y-4",children:[j&&e.jsxs(z,{className:"border-green-200 bg-green-50",children:[e.jsx(q,{className:"h-4 w-4 text-green-600"}),e.jsxs(R,{className:"text-green-800",children:[e.jsxs("strong",{children:["Gas Cost Reduced by ",j,"!"]})," Batch processing saved significant transaction fees."]})]}),c.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"text-muted-foreground",children:"Pending Credentials"}),e.jsxs(w,{variant:"secondary",children:[c.length," credentials"]})]}),e.jsxs("div",{className:"grid grid-cols-3 gap-2 text-center",children:[e.jsxs("div",{className:"bg-blue-50 rounded-lg p-3",children:[e.jsx("div",{className:"text-2xl font-bold text-blue-600",children:c.filter(r=>r.credential_type==="SKILL").length}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Skills"})]}),e.jsxs("div",{className:"bg-green-50 rounded-lg p-3",children:[e.jsx("div",{className:"text-2xl font-bold text-green-600",children:c.filter(r=>r.credential_type==="EDUCATION").length}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Education"})]}),e.jsxs("div",{className:"bg-purple-50 rounded-lg p-3",children:[e.jsx("div",{className:"text-2xl font-bold text-purple-600",children:c.filter(r=>r.credential_type==="EMPLOYMENT").length}),e.jsx("div",{className:"text-xs text-muted-foreground",children:"Employment"})]})]})]}),e.jsxs("div",{className:"bg-muted/50 rounded-lg p-4 space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:"Individual Transactions:"}),e.jsxs("span",{className:"font-mono",children:["~",c.length*21e3," gas"]})]}),e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{children:"Batch Transaction:"}),e.jsx("span",{className:"font-mono text-green-600",children:"~21000 gas"})]}),e.jsxs("div",{className:"flex items-center justify-between text-sm font-semibold",children:[e.jsx("span",{children:"Estimated Savings:"}),e.jsxs("span",{className:"text-green-600",children:["~",((1-21e3/(c.length*21e3))*100).toFixed(0),"%"]})]})]}),e.jsx(k,{onClick:t,disabled:l,className:"w-full",size:"lg",children:l?e.jsxs(e.Fragment,{children:[e.jsx(I,{className:"h-4 w-4 mr-2 animate-spin"}),"Processing Batch..."]}):e.jsxs(e.Fragment,{children:[e.jsx(K,{className:"h-4 w-4 mr-2"}),"Process ",c.length," Credentials"]})}),e.jsx("p",{className:"text-xs text-muted-foreground text-center",children:"All credentials will be verified via Merkle tree proof on Polygon blockchain"})]}):e.jsxs("div",{className:"text-center py-8",children:[e.jsx(Y,{className:"h-12 w-12 text-green-500 mx-auto mb-4"}),e.jsx("p",{className:"text-muted-foreground",children:"All credentials are on-chain!"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:"No pending credentials to process"})]})]})]})}const xe=async(i,c,m,y,f)=>{const l=`
7    <!DOCTYPE html>
8    <html>
9    <head>
10      <meta charset="utf-8">
11      <title>${i} - Digital Passport</title>
12      <style>
13        * { margin: 0; padding: 0; box-sizing: border-box; }
14        body { 
15          font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
16          color: #1a1a1a;
17          line-height: 1.6;
18          padding: 40px;
19          background: #ffffff;
20        }
21        .header {
22          border-bottom: 3px solid #0066cc;
23          padding-bottom: 20px;
24          margin-bottom: 30px;
25        }
26        .header h1 {
27          font-size: 32px;
28          color: #0066cc;
29          margin-bottom: 8px;
30        }
31        .header .subtitle {
32          font-size: 14px;
33          color: #666;
34        }
35        .did-box {
36          background: #f5f5f5;
37          padding: 15px;
38          border-radius: 8px;
39          margin: 20px 0;
40          border-left: 4px solid #0066cc;
41        }
42        .did-box strong {
43          display: block;
44          margin-bottom: 5px;
45          color: #0066cc;
46        }
47        .did-box code {
48          font-family: 'Courier New', monospace;
49          font-size: 11px;
50          color: #333;
51          word-break: break-all;
52        }
53        .section {
54          margin: 30px 0;
55          page-break-inside: avoid;
56        }
57        .section-title {
58          font-size: 20px;
59          color: #0066cc;
60          margin-bottom: 15px;
61          padding-bottom: 8px;
62          border-bottom: 2px solid #e0e0e0;
63        }
64        .credential-card {
65          background: #fafafa;
66          border: 1px solid #e0e0e0;
67          border-radius: 8px;
68          padding: 20px;
69          margin-bottom: 15px;
70          page-break-inside: avoid;
71        }
72        .credential-card h3 {
73          font-size: 16px;
74          color: #1a1a1a;
75          margin-bottom: 8px;
76        }
77        .credential-card .meta {
78          font-size: 13px;
79          color: #666;
80          margin-bottom: 12px;
81        }
82        .blockchain-info {
83          background: #e8f4ff;
84          border: 1px solid #b3d9ff;
85          border-radius: 6px;
86          padding: 12px;
87          margin-top: 10px;
88        }
89        .blockchain-info .label {
90          font-size: 11px;
91          color: #0066cc;
92          font-weight: 600;
93          text-transform: uppercase;
94          letter-spacing: 0.5px;
95        }
96        .blockchain-info .value {
97          font-family: 'Courier New', monospace;
98          font-size: 10px;
99          color: #333;
100          word-break: break-all;
101          margin-top: 4px;
102        }
103        .stats-grid {
104          display: grid;
105          grid-template-columns: repeat(4, 1fr);
106          gap: 15px;
107          margin: 20px 0;
108        }
109        .stat-box {
110          text-align: center;
111          padding: 15px;
112          background: #f5f5f5;
113          border-radius: 6px;
114        }
115        .stat-box .number {
116          font-size: 28px;
117          font-weight: bold;
118          color: #0066cc;
119        }
120        .stat-box .label {
121          font-size: 12px;
122          color: #666;
123          margin-top: 5px;
124        }
125        .footer {
126          margin-top: 40px;
127          padding-top: 20px;
128          border-top: 2px solid #e0e0e0;
129          font-size: 11px;
130          color: #666;
131          text-align: center;
132        }
133        .verification-badge {
134          display: inline-block;
135          background: #10b981;
136          color: white;
137          padding: 4px 12px;
138          border-radius: 12px;
139          font-size: 11px;
140          font-weight: 600;
141          margin-left: 10px;
142        }
143      </style>
144    </head>
145    <body>
146      <div class="header">
147        <h1>🛂 Digital Passport</h1>
148        <p class="subtitle">Blockchain-Verified Professional Credentials</p>
149        <h2 style="margin-top: 15px; color: #333;">${i}</h2>
150      </div>
151
152      <div class="did-box">
153        <strong>🔐 Decentralized Identity (DID)</strong>
154        <code>${c}</code>
155      </div>
156
157      <div class="stats-grid">
158        <div class="stat-box">
159          <div class="number">${m.length+y.length+f.length}</div>
160          <div class="label">Total Credentials</div>
161        </div>
162        <div class="stat-box">
163          <div class="number">${m.length}</div>
164          <div class="label">Skills</div>
165        </div>
166        <div class="stat-box">
167          <div class="number">${y.length}</div>
168          <div class="label">Education</div>
169        </div>
170        <div class="stat-box">
171          <div class="number">${f.length}</div>
172          <div class="label">Employment</div>
173        </div>
174      </div>
175
176      ${y.length>0?`
177        <div class="section">
178          <h2 class="section-title">🎓 Education</h2>
179          ${y.map(a=>`
180            <div class="credential-card">
181              <h3>${a.degree_level} in ${a.degree_field}
182                <span class="verification-badge">✓ VERIFIED</span>
183              </h3>
184              <div class="meta">
185                ${a.institution_name} • Graduated: ${new Date(a.graduation_date).toLocaleDateString()}
186                ${a.gpa?` • GPA: ${a.gpa}`:""}
187              </div>
188              <div class="blockchain-info">
189                <div class="label">Blockchain Credential ID</div>
190                <div class="value">${a.credential_id}</div>
191                ${a.blockchain_record_id?`
192                  <div class="label" style="margin-top: 8px;">Transaction Hash</div>
193                  <div class="value">${a.blockchain_record_id}</div>
194                `:""}
195              </div>
196            </div>
197          `).join("")}
198        </div>
199      `:""}
200
201      ${f.length>0?`
202        <div class="section">
203          <h2 class="section-title">💼 Employment History</h2>
204          ${f.map(a=>`
205            <div class="credential-card">
206              <h3>${a.job_title}
207                <span class="verification-badge">✓ VERIFIED</span>
208              </h3>
209              <div class="meta">
210                ${a.employer_name} • 
211                ${new Date(a.employment_start_date).toLocaleDateString()} - 
212                ${a.employment_end_date?new Date(a.employment_end_date).toLocaleDateString():"Present"}
213                ${a.employment_duration_months?` • ${a.employment_duration_months} months`:""}
214              </div>
215              <div class="blockchain-info">
216                <div class="label">Blockchain Credential ID</div>
217                <div class="value">${a.credential_id}</div>
218                ${a.blockchain_record_id?`
219                  <div class="label" style="margin-top: 8px;">Transaction Hash</div>
220                  <div class="value">${a.blockchain_record_id}</div>
221                `:""}
222              </div>
223            </div>
224          `).join("")}
225        </div>
226      `:""}
227
228      ${m.length>0?`
229        <div class="section">
230          <h2 class="section-title">🏆 Certified Skills</h2>
231          ${m.map(a=>{var h;return`
232            <div class="credential-card">
233              <h3>${((h=a.skills)==null?void 0:h.name)||a.skill_id}
234                <span class="verification-badge">✓ VERIFIED</span>
235              </h3>
236              <div class="meta">
237                Proficiency: ${Math.round(a.proficiency_level*100)}% • 
238                ${a.proficiency_description}
239              </div>
240              <div class="blockchain-info">
241                <div class="label">Blockchain Credential ID</div>
242                <div class="value">${a.credential_id}</div>
243                ${a.blockchain_record_id?`
244                  <div class="label" style="margin-top: 8px;">Transaction Hash</div>
245                  <div class="value">${a.blockchain_record_id}</div>
246                `:""}
247              </div>
248            </div>
249          `}).join("")}
250        </div>
251      `:""}
252
253      <div class="footer">
254        <p><strong>Blockchain Security Notice</strong></p>
255        <p>All credentials are cryptographically signed and recorded on the Polygon blockchain.</p>
256        <p>Transaction hashes can be independently verified at mumbai.polygonscan.com</p>
257        <p style="margin-top: 10px;">Generated on ${new Date().toLocaleString()} • GenAIx Digital Passport</p>
258      </div>
259    </body>
260    </html>
261  `,x=document.createElement("div");x.innerHTML=l;const j={margin:.5,filename:`${i.replace(/\s+/g,"_")}_Digital_Passport.pdf`,image:{type:"jpeg",quality:.98},html2canvas:{scale:2,useCORS:!0},jsPDF:{unit:"in",format:"letter",orientation:"portrait"}};try{return await ie().set(j).from(x).save(),!0}catch(a){throw console.error("PDF generation error:",a),a}};function $e(){const{user:i,loading:c}=J(),m=Q(),[y,f]=b.useState(!0),[l,x]=b.useState(null),[j,a]=b.useState([]),[h,t]=b.useState([]),[r,n]=b.useState([]);b.useEffect(()=>{!c&&!i?m("/auth"):i&&v()},[i,c,m]);const v=async()=>{if(i)try{const s=G(i.uid),{data:p}=await N.from("profiles").select("*").eq("user_id",s).single();x(p);const{data:D}=await N.from("skill_credentials").select("*, skills(name)").eq("holder_user_id",s).eq("credential_status","ACTIVE");a(D||[]);const{data:_}=await N.from("educational_degree_credentials").select("*").eq("holder_user_id",s).eq("credential_status","ACTIVE");t(_||[]);const{data:E}=await N.from("employment_history_credentials").select("*").eq("holder_user_id",s).eq("credential_status","ACTIVE");n(E||[])}catch(s){console.error("Error loading passport data:",s),o.error("Failed to load passport data")}finally{f(!1)}};if(c||y)return e.jsx("div",{className:"flex items-center justify-center min-h-screen",children:e.jsxs("div",{className:"text-center",children:[e.jsx(F,{className:"h-12 w-12 text-primary animate-pulse mx-auto mb-4"}),e.jsx("p",{className:"text-muted-foreground",children:"Loading your digital passport..."})]})});const d=j.length+h.length+r.length;return e.jsxs(e.Fragment,{children:[e.jsx(ae,{title:"My Digital Passport | GenAIx",description:"View your complete blockchain-verified digital passport with all credentials, education, and employment history."}),e.jsxs("div",{className:"container mx-auto px-4 py-8 max-w-7xl",children:[e.jsxs("div",{className:"mb-8",children:[e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-4 mb-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-4xl font-bold mb-2",children:"My Digital Passport"}),e.jsx("p",{className:"text-muted-foreground",children:"Blockchain-verified credentials • Portable • Privacy-first"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(k,{variant:"outline",onClick:async()=>{try{const s=(l==null?void 0:l.full_name)||i.email||"User",p=(l==null?void 0:l.did)||"N/A";
261await xe(s,p,j,h,r),o.success("PDF exported successfully!")}catch{o.error("Failed to export PDF")}},children:[e.jsx(le,{className:"h-4 w-4 mr-2"}),"Export PDF"]}),e.jsxs(k,{onClick:()=>m("/credentials"),children:[e.jsx(ne,{className:"h-4 w-4 mr-2"}),"Share Credentials"]})]})]}),e.jsx(u,{className:"mb-6 border-primary/20 bg-gradient-to-r from-primary/5 via-background to-accent/5",children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:"p-3 rounded-xl bg-primary/10",children:e.jsx(F,{className:"h-6 w-6 text-primary"})}),e.jsxs("div",{className:"flex-1",children:[e.jsx("h3",{className:"font-semibold mb-2",children:"Why GenAIx Digital Passport is Unique"}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4 text-sm",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(w,{variant:"outline",className:"shrink-0 bg-green-500/10 text-green-600 border-green-500/30",children:"Patent Pending"}),e.jsx("span",{className:"text-muted-foreground",children:"Temporal skill decay tracking predicts when skills need refreshing"})]}),e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(w,{variant:"outline",className:"shrink-0 bg-blue-500/10 text-blue-600 border-blue-500/30",children:"Polygon Mainnet"}),e.jsx("span",{className:"text-muted-foreground",children:"Credentials verified on real blockchain, not testnet"})]}),e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(w,{variant:"outline",className:"shrink-0 bg-purple-500/10 text-purple-600 border-purple-500/30",children:"Resume Upload"}),e.jsx("span",{className:"text-muted-foreground",children:"AI parses your resume to auto-generate credentials"})]})]})]})]})})}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-4",children:[e.jsx(u,{children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Total Credentials"}),e.jsx("p",{className:"text-3xl font-bold",children:d})]}),e.jsx(F,{className:"h-8 w-8 text-primary"})]})})}),e.jsx(u,{children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Skills"}),e.jsx("p",{className:"text-3xl font-bold",children:j.length})]}),e.jsx($,{className:"h-8 w-8 text-blue-500"})]})})}),e.jsx(u,{children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Education"}),e.jsx("p",{className:"text-3xl font-bold",children:h.length})]}),e.jsx(U,{className:"h-8 w-8 text-green-500"})]})})}),e.jsx(u,{children:e.jsx(g,{className:"pt-6",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Employment"}),e.jsx("p",{className:"text-3xl font-bold",children:r.length})]}),e.jsx(M,{className:"h-8 w-8 text-purple-500"})]})})})]})]}),d>0&&i&&e.jsx("div",{className:"mb-8",children:e.jsx(me,{userId:i.uid})}),d>0&&j.length>0&&i&&e.jsx("div",{className:"mb-8",children:e.jsx(oe,{userId:i.uid})}),d===0&&i&&e.jsx("div",{className:"mb-8",children:e.jsx(de,{userId:i.uid,onComplete:v})}),l&&e.jsxs(u,{className:"mb-8",children:[e.jsx(P,{children:e.jsxs(C,{className:"flex items-center gap-2",children:[e.jsx(X,{className:"h-5 w-5"}),"Profile Information"]})}),e.jsx(g,{children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Full Name"}),e.jsx("p",{className:"font-medium",children:l.full_name||"Not set"})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Email"}),e.jsx("p",{className:"font-medium",children:l.email})]}),l.company_name&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Company"}),e.jsx("p",{className:"font-medium",children:l.company_name})]}),l.location&&e.jsxs("div",{children:[e.jsx("p",{className:"text-sm text-muted-foreground",children:"Location"}),e.jsx("p",{className:"font-medium",children:l.location})]})]})})]}),e.jsxs(ee,{defaultValue:"skills",className:"space-y-6",children:[e.jsxs(se,{className:"grid w-full grid-cols-3",children:[e.jsxs(A,{value:"skills",children:[e.jsx($,{className:"h-4 w-4 mr-2"}),"Skills (",j.length,")"]}),e.jsxs(A,{value:"education",children:[e.jsx(U,{className:"h-4 w-4 mr-2"}),"Education (",h.length,")"]}),e.jsxs(A,{value:"employment",children:[e.jsx(M,{className:"h-4 w-4 mr-2"}),"Employment (",r.length,")"]})]}),e.jsx(L,{value:"skills",className:"space-y-4",children:j.length===0?e.jsx(u,{className:"border-dashed",children:e.jsxs(g,{className:"flex flex-col items-center justify-center py-12",children:[e.jsx($,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("p",{className:"text-muted-foreground mb-4",children:"No skill credentials yet"}),e.jsx(k,{onClick:()=>m("/courses"),children:"Browse Courses"})]})}):j.map(s=>{var p;return e.jsxs(u,{children:[e.jsxs(P,{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(C,{children:((p=s.skills)==null?void 0:p.name)||s.skill_id}),e.jsxs(w,{children:[Math.round(s.proficiency_level*100),"% Proficient"]})]}),e.jsx(S,{children:s.proficiency_description})]}),e.jsx(g,{children:e.jsx(B,{credential:s,credentialType:"SKILL"})})]},s.credential_id)})}),e.jsx(L,{value:"education",className:"space-y-4",children:h.length===0?e.jsx(u,{className:"border-dashed",children:e.jsxs(g,{className:"flex flex-col items-center justify-center py-12",children:[e.jsx(U,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("p",{className:"text-muted-foreground",children:"No education credentials yet"})]})}):h.map(s=>e.jsxs(u,{children:[e.jsxs(P,{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(C,{children:[s.degree_level," in ",s.degree_field]}),e.jsx(w,{variant:"outline",children:s.institution_name})]}),e.jsxs(S,{children:["Graduated: ",new Date(s.graduation_date).toLocaleDateString(),s.gpa&&` • GPA: ${s.gpa}`]})]}
261),e.jsx(g,{children:e.jsx(B,{credential:s,credentialType:"EDUCATION"})})]},s.credential_id))}),e.jsx(L,{value:"employment",className:"space-y-4",children:r.length===0?e.jsx(u,{className:"border-dashed",children:e.jsxs(g,{className:"flex flex-col items-center justify-center py-12",children:[e.jsx(M,{className:"h-12 w-12 text-muted-foreground mb-4"}),e.jsx("p",{className:"text-muted-foreground",children:"No employment credentials yet"})]})}):r.map(s=>e.jsxs(u,{children:[e.jsxs(P,{children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(C,{children:s.job_title}),e.jsxs(w,{variant:"outline",children:[e.jsx(ce,{className:"h-3 w-3 mr-1"}),s.employer_name]})]}),e.jsxs(S,{children:[new Date(s.employment_start_date).toLocaleDateString()," - "," ",s.employment_end_date?new Date(s.employment_end_date).toLocaleDateString():"Present",s.employment_duration_months&&` • ${s.employment_duration_months} months`]})]}),e.jsx(g,{children:e.jsx(B,{credential:s,credentialType:"EMPLOYMENT"})})]},s.credential_id))})]})]})]})}export{$e as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.