Mobile Home Page Update

This commit is contained in:
2026-01-25 15:42:20 +00:00
parent 34eba52461
commit 372b797f3e

View File

@@ -1,540 +1,245 @@
<script lang="ts"> <script lang="ts">
import { onMount } from "svelte"; import { onMount } from "svelte";
import Icon from "@iconify/svelte"; import Icon from "@iconify/svelte";
const scanHistory = [ const scanHistory = [
{ {
id: 1, id: 1,
name: "Plastic Water Bottle", name: "Plastic Water Bottle",
date: "Today, 10:45 AM", date: "Today, 10:45 AM",
severity: "High", severity: "High",
icon: "ri:drop-fill", image: "/water-bottle.png",
}, impact: "Negative Impact",
{ },
id: 2, {
name: "Organic Banana", id: 2,
date: "Yesterday, 3:20 PM", name: "Organic Banana",
severity: "Low", date: "Yesterday, 3:20 PM",
icon: "ri:plant-fill", severity: "Low",
}, image: "/banana.png",
{ impact: "Positive Choice",
id: 3, },
name: "Aluminum Soda Can", {
date: "Mon, 12:15 PM", id: 3,
severity: "Low", name: "Aluminum Soda Can",
icon: "ri:cup-fill", date: "Mon, 12:15 PM",
}, severity: "Low",
{ image: "/soda-can.png",
id: 4, impact: "Recyclable",
name: "Takeout Container", },
date: "Sun, 8:30 PM", {
severity: "Medium", id: 4,
icon: "ri:box-3-fill", name: "Takeout Container",
}, date: "Sun, 8:30 PM",
{ severity: "Medium",
id: 5, image: "/container.png",
name: "Shampoo Bottle", impact: "Mixed Materials",
date: "Sat, 11:00 AM", },
severity: "High", {
icon: "ri:flask-fill", id: 5,
}, name: "Shampoo Bottle",
]; date: "Sat, 11:00 AM",
severity: "High",
let greeting = $state("Hello"); image: "/shampoo.png",
impact: "High Plastic",
onMount(() => { },
const hour = new Date().getHours(); ];
if (hour < 12) greeting = "Good morning";
else if (hour < 17) greeting = "Good afternoon"; interface ScanItem {
else greeting = "Good evening"; id: number;
}); name: string;
date: string;
function getSeverityClass(severity: string): string { severity: string;
return severity.toLowerCase(); image: string;
} impact: string;
}
function getSeverityColor(severity: string): string {
switch (severity.toLowerCase()) { let selectedScan = $state<ScanItem | null>(null);
case "low":
return "#34d399"; function openScan(scan: ScanItem) {
case "medium": selectedScan = scan;
return "#fb923c"; }
case "high":
return "#f87171"; function closeScan() {
default: selectedScan = null;
return "#9ca3af"; }
}
} let greeting = $state("Hello");
</script>
onMount(() => {
<div class="mobile-home"> const hour = new Date().getHours();
<header class="header"> if (hour < 12) greeting = "Good morning";
<div class="header-left"> else if (hour < 17) greeting = "Good afternoon";
<div class="avatar"> else greeting = "Good evening";
<img });
src="/ethix-logo.png"
alt="Ethix Logo" function getSeverityClass(severity: string): string {
class="avatar-logo" return severity.toLowerCase();
/> }
</div> </script>
<div class="header-text">
<span class="greeting">{greeting}</span> <div class="min-h-screen bg-[#051f18] text-white px-5 pt-4 pb-32">
<h1 class="username">Eco Warrior</h1>
</div> <section class="flex gap-3 mb-7">
</div> <div
<button class="notification-btn" aria-label="Notifications"> class="flex-1 flex flex-col items-center gap-2 py-4 px-2 bg-[#0d2e25] border border-[#1f473b] rounded-2xl"
<Icon >
icon="ri:notification-3-line" <div
width="24" class="w-9 h-9 bg-emerald-500/10 rounded-xl flex items-center justify-center"
style="color: #9ca3af;" >
/> <Icon
<span class="notif-badge">2</span> icon="ri:qr-scan-2-line"
</button> width="20"
</header> class="text-emerald-400"
/>
<section class="impact-hero"> </div>
<div class="impact-main"> <span class="text-lg font-extrabold text-white">47</span>
<span class="impact-label">Your Carbon Savings</span> <span
<div class="impact-value"> class="text-[10px] text-gray-400 uppercase tracking-wide font-semibold"
<span class="impact-number">23</span> >scans</span
<span class="impact-unit">kg CO₂</span> >
</div> </div>
<div class="impact-comparison"> <div
<Icon icon="ri:car-fill" width="16" style="color: #6ee7b7;" /> class="flex-1 flex flex-col items-center gap-2 py-4 px-2 bg-[#0d2e25] border border-[#1f473b] rounded-2xl"
<span>≈ driving 92 km less</span> >
</div> <div
</div> class="w-9 h-9 bg-emerald-500/10 rounded-xl flex items-center justify-center"
<div class="impact-visual"> >
<div class="tree-ring"> <Icon
<Icon icon="ri:tree-fill" width="32" style="color: #10b981;" /> icon="ri:checkbox-circle-fill"
</div> width="20"
<span class="tree-count">2 trees planted</span> class="text-emerald-400"
</div> />
</section> </div>
<span class="text-lg font-extrabold text-white">32</span>
<section class="stats-row"> <span
<div class="stat-pill"> class="text-[10px] text-gray-400 uppercase tracking-wide font-semibold"
<div class="stat-icon"> >eco picks</span
<Icon >
icon="ri:qr-scan-2-line" </div>
width="20" </section>
style="color: #34d399;"
/> <section class="recent-section">
</div> <div class="flex flex-col gap-2.5">
<span class="stat-value">47</span> {#each scanHistory as item (item.id)}
<span class="stat-label">scans</span> <button
</div> class="flex items-center gap-3.5 p-3 bg-[#0d2e25] border border-[#1f473b] rounded-2xl cursor-pointer w-full text-left transition-transform active:scale-98 active:bg-[#1f473b]"
<div class="stat-pill"> onclick={() => openScan(item)}
<div class="stat-icon eco"> aria-label="View {item.name}"
<Icon >
icon="ri:checkbox-circle-fill" <div class="w-12 h-12 rounded-xl overflow-hidden shrink-0">
width="20" {#if item.image}
style="color: #34d399;" <img
/> src={item.image}
</div> alt={item.name}
<span class="stat-value">32</span> class="w-full h-full object-cover"
<span class="stat-label">eco picks</span> />
</div> {:else}
<div class="stat-pill"> <div
<div class="stat-icon score"> class="w-full h-full flex items-center justify-center font-bold text-[#051f18]"
<Icon icon="ri:star-fill" width="20" style="color: #fbbf24;" /> style="background-color: {getSeverityClass(
</div> item.severity,
<span class="stat-value">78%</span> ) === 'high'
<span class="stat-label">score</span> ? '#fca5a5'
</div> : '#86efac'}"
</section> >
<span class="text-lg">{item.name[0]}</span>
<section class="recent-section"> </div>
<div class="section-header"> {/if}
<h2>Recent Scans</h2> </div>
<a href="/history" class="see-all"> <div class="flex-1 flex flex-col gap-0.5 min-w-0">
See all <span class="text-sm font-semibold text-white truncate"
<Icon icon="ri:arrow-right-s-line" width="16" /> >{item.name}</span
</a> >
</div> <span class="text-xs text-gray-400">{item.date}</span>
</div>
<div class="scan-list"> <span
{#each scanHistory as item (item.id)} class="px-2.5 py-1 rounded-full text-[10px] font-bold uppercase tracking-wide {item.severity.toLowerCase() ===
<button class="scan-item" aria-label="View {item.name}"> 'high'
<div ? 'bg-red-400/10 text-red-400 border border-red-400/20'
class="item-icon" : item.severity.toLowerCase() === 'medium'
style="color: {getSeverityColor(item.severity)};" ? 'bg-orange-400/10 text-orange-400 border border-orange-400/20'
> : 'bg-emerald-400/10 text-emerald-400 border border-emerald-400/20'}"
<Icon icon={item.icon} width="24" /> >
</div> {item.severity}
<div class="item-info"> </span>
<span class="item-name">{item.name}</span> </button>
<span class="item-date">{item.date}</span> {/each}
</div> </div>
<span </section>
class="severity-tag {getSeverityClass(item.severity)}"
> {#if selectedScan}
{item.severity} <div
</span> class="fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center p-5"
</button> role="button"
{/each} tabindex="0"
</div> onkeydown={(e) => e.key === "Escape" && closeScan()}
</section> onclick={closeScan}
>
<section class="tip-card"> <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<div class="tip-icon"> <div
<Icon class="bg-[#0d2e25] border border-[#1f473b] rounded-3xl w-full max-w-[340px] p-6 relative shadow-[0_20px_50px_rgba(0,0,0,0.5)]"
icon="ri:lightbulb-flash-fill" role="document"
width="22" tabindex="-1"
style="color: #fbbf24;" onkeydown={(e) => e.key === "Escape" && closeScan()}
/> onclick={(e) => e.stopPropagation()}
</div> >
<div class="tip-text"> <button
<strong>Daily Tip:</strong> Bring reusable bags shopping to cut 500 plastic class="absolute top-4 right-4 bg-transparent border-none text-gray-400 cursor-pointer"
bags per year! onclick={closeScan}
</div> >
</section> <Icon icon="ri:close-fill" width="24" />
</div> </button>
<div class="text-center mb-5">
<style> <span
.mobile-home { class="text-xs text-gray-400 uppercase tracking-widest"
padding: 16px 20px 120px; >{selectedScan.date}</span
min-height: 100vh; >
background: #051f18; <h2 class="text-xl text-white m-0 mt-1">Scan Report</h2>
color: white; </div>
} <div
class="w-full h-[200px] bg-black rounded-2xl mb-5 overflow-hidden"
.header { >
display: flex; {#if selectedScan.image}
justify-content: space-between; <img
align-items: center; src={selectedScan.image}
margin-bottom: 24px; alt={selectedScan.name}
padding-top: 8px; class="w-full h-full object-cover"
} />
{:else}
.header-left { <div
display: flex; class="w-full h-full flex items-center justify-center"
align-items: center; style="background-color: {getSeverityClass(
gap: 12px; selectedScan.severity,
} ) === 'high'
? '#fca5a5'
.avatar { : '#86efac'}"
width: 48px; >
height: 48px; <span class="text-6xl text-[#051f18] font-black"
background: #0d2e25; >{selectedScan.name[0]}</span
border: 1px solid #1f473b; >
border-radius: 50%; </div>
display: flex; {/if}
align-items: center; </div>
justify-content: center; <div class="text-center">
overflow: hidden; <h3 class="text-lg text-white m-0 mb-1">
} {selectedScan.name}
</h3>
.avatar-logo { <p class="text-gray-300 text-sm mb-3">
width: 36px; {selectedScan.impact}
height: 36px; </p>
object-fit: contain; <div
} class="inline-block px-3 py-1.5 rounded-full text-xs font-bold uppercase {selectedScan.severity.toLowerCase() ===
'high'
.header-text { ? 'bg-red-400/20 text-red-400'
display: flex; : selectedScan.severity.toLowerCase() === 'medium'
flex-direction: column; ? 'bg-orange-400/20 text-orange-400'
} : 'bg-emerald-400/20 text-emerald-400'}"
>
.greeting { Severity: {selectedScan.severity}
font-size: 13px; </div>
color: #9ca3af; </div>
} </div>
</div>
.username { {/if}
font-size: 20px; </div>
font-weight: 800;
color: white;
margin: 0;
}
.notification-btn {
position: relative;
width: 44px;
height: 44px;
background: #0d2e25;
border: 1px solid #1f473b;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.notif-badge {
position: absolute;
top: -2px;
right: -2px;
width: 18px;
height: 18px;
background: #ef4444;
color: white;
font-size: 10px;
font-weight: 700;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid #051f18;
}
.impact-hero {
display: flex;
justify-content: space-between;
align-items: center;
background: #0d2e25;
border: 1px solid #1f473b;
border-radius: 20px;
padding: 24px;
margin-bottom: 24px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
.impact-main {
display: flex;
flex-direction: column;
gap: 4px;
}
.impact-label {
font-size: 11px;
color: #6ee7b7;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 700;
}
.impact-value {
display: flex;
align-items: baseline;
gap: 6px;
}
.impact-number {
font-size: 36px;
font-weight: 900;
color: white;
line-height: 1;
}
.impact-unit {
font-size: 16px;
color: #9ca3af;
font-weight: 600;
}
.impact-comparison {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: #d1fae5;
margin-top: 8px;
}
.impact-visual {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.tree-ring {
width: 64px;
height: 64px;
background: rgba(16, 185, 129, 0.1);
border: 1px solid rgba(16, 185, 129, 0.3);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.tree-count {
font-size: 11px;
color: #34d399;
font-weight: 700;
}
.stats-row {
display: flex;
gap: 12px;
margin-bottom: 28px;
}
.stat-pill {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 16px 8px;
background: #0d2e25;
border: 1px solid #1f473b;
border-radius: 16px;
}
.stat-icon {
width: 36px;
height: 36px;
background: rgba(16, 185, 129, 0.1);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.stat-value {
font-size: 18px;
font-weight: 800;
color: white;
}
.stat-label {
font-size: 10px;
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 0.5px;
font-weight: 600;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.section-header h2 {
font-size: 16px;
font-weight: 800;
color: white;
margin: 0;
}
.see-all {
display: flex;
align-items: center;
gap: 2px;
font-size: 13px;
color: #34d399;
text-decoration: none;
font-weight: 600;
}
.scan-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.scan-item {
display: flex;
align-items: center;
gap: 14px;
padding: 12px;
background: #0d2e25;
border: 1px solid #1f473b;
border-radius: 16px;
cursor: pointer;
width: 100%;
text-align: left;
transition: transform 0.1s;
}
.scan-item:active {
transform: scale(0.98);
background: #1f473b;
}
.item-icon {
width: 44px;
height: 44px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
background: #051f18;
}
.item-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.item-name {
font-size: 14px;
font-weight: 600;
color: white;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item-date {
font-size: 12px;
color: #9ca3af;
}
.severity-tag {
padding: 4px 10px;
border-radius: 20px;
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.3px;
}
.severity-tag.low {
background: rgba(52, 211, 153, 0.1);
color: #34d399;
border: 1px solid rgba(52, 211, 153, 0.2);
}
.severity-tag.medium {
background: rgba(251, 146, 60, 0.1);
color: #fb923c;
border: 1px solid rgba(251, 146, 60, 0.2);
}
.severity-tag.high {
background: rgba(248, 113, 113, 0.1);
color: #f87171;
border: 1px solid rgba(248, 113, 113, 0.2);
}
.tip-card {
display: flex;
gap: 14px;
padding: 20px;
background: #0d2e25;
border: 1px solid #1f473b;
border-radius: 16px;
margin-top: 24px;
}
.tip-icon {
width: 40px;
height: 40px;
background: rgba(251, 191, 36, 0.1);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.tip-text {
font-size: 13px;
color: #d1d5db;
line-height: 1.5;
}
.tip-text strong {
color: white;
font-weight: 700;
}
</style>