mirror of
https://github.com/SirBlobby/Hoya26.git
synced 2026-02-03 19:24:34 -05:00
Mobile and Docker Update
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM node:20-alpine AS builder
|
||||
FROM oven/bun:1 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -7,24 +7,24 @@ WORKDIR /app
|
||||
COPY package.json ./
|
||||
|
||||
# Install dependencies
|
||||
RUN npm install
|
||||
RUN bun install
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the SvelteKit app
|
||||
RUN npm run build
|
||||
RUN bun run build
|
||||
|
||||
# Production stage
|
||||
FROM node:20-alpine AS production
|
||||
FROM oven/bun:1 AS production
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package.json for production dependencies
|
||||
# Copy package.json and lockfile for production dependencies
|
||||
COPY package.json ./
|
||||
|
||||
# Install only production dependencies
|
||||
RUN npm install --omit=dev
|
||||
RUN bun install --production
|
||||
|
||||
# Copy built files from builder
|
||||
COPY --from=builder /app/build ./build
|
||||
@@ -38,4 +38,4 @@ ENV NODE_ENV=production
|
||||
ENV PORT=3000
|
||||
|
||||
# Start the server
|
||||
CMD ["node", "server/index.js"]
|
||||
CMD ["bun", "server/index.js"]
|
||||
|
||||
@@ -25,7 +25,7 @@ app.use(express.urlencoded({ extended: true, limit: '50mb' }));
|
||||
*/
|
||||
app.use('/api', async (req, res) => {
|
||||
const targetUrl = `${API_URL}${req.originalUrl}`;
|
||||
|
||||
|
||||
try {
|
||||
const fetchOptions = {
|
||||
method: req.method,
|
||||
@@ -41,10 +41,10 @@ app.use('/api', async (req, res) => {
|
||||
}
|
||||
|
||||
const response = await fetch(targetUrl, fetchOptions);
|
||||
|
||||
|
||||
// Get content type from response
|
||||
const contentType = response.headers.get('content-type');
|
||||
|
||||
|
||||
// Set response headers
|
||||
res.status(response.status);
|
||||
if (contentType) {
|
||||
@@ -52,7 +52,7 @@ app.use('/api', async (req, res) => {
|
||||
}
|
||||
|
||||
// Handle different response types
|
||||
if (contentType && (contentType.includes('application/pdf') ||
|
||||
if (contentType && (contentType.includes('application/pdf') ||
|
||||
contentType.includes('text/plain') ||
|
||||
contentType.includes('application/octet-stream'))) {
|
||||
// Binary/file responses
|
||||
@@ -78,7 +78,7 @@ const buildPath = path.join(__dirname, '../build');
|
||||
app.use(express.static(buildPath));
|
||||
|
||||
// SPA fallback - serve index.html for all other routes
|
||||
app.get('*', (req, res) => {
|
||||
app.get(/.*/, (req, res) => {
|
||||
res.sendFile(path.join(buildPath, 'index.html'));
|
||||
});
|
||||
|
||||
|
||||
@@ -1,172 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte";
|
||||
import Icon from "@iconify/svelte";
|
||||
|
||||
let shouldShow = $state(false);
|
||||
|
||||
onMount(() => {
|
||||
// Check if iOS
|
||||
const isIOS =
|
||||
/iPad|iPhone|iPod/.test(navigator.userAgent) &&
|
||||
!(window as any).MSStream;
|
||||
|
||||
// Check if standalone
|
||||
const isStandalone =
|
||||
(window.navigator as any).standalone ||
|
||||
window.matchMedia("(display-mode: standalone)").matches;
|
||||
|
||||
// Check if mobile size
|
||||
const isMobileSize = window.innerWidth <= 768;
|
||||
|
||||
if (isIOS && isMobileSize && !isStandalone) {
|
||||
shouldShow = true;
|
||||
}
|
||||
|
||||
// For debugging/demo purposes (uncomment to test on desktop)
|
||||
// if (window.innerWidth <= 768 && !isStandalone) shouldShow = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if shouldShow}
|
||||
<div class="install-overlay">
|
||||
<div class="install-card">
|
||||
<div class="icon-wrapper">
|
||||
<img src="/ethix-logo.png" alt="Ethix Logo" />
|
||||
</div>
|
||||
|
||||
<h1>Install Ethix</h1>
|
||||
<p>To use Ethix, please add this website to your home screen.</p>
|
||||
|
||||
<div class="instructions">
|
||||
<div class="step">
|
||||
<span class="step-num">1</span>
|
||||
<span
|
||||
>Tap the Share button <Icon
|
||||
icon="ios-share"
|
||||
width="20"
|
||||
style="vertical-align: middle; color: #3b82f6;"
|
||||
/> below</span
|
||||
>
|
||||
</div>
|
||||
<div class="step">
|
||||
<span class="step-num">2</span>
|
||||
<span>Select <strong>"Add to Home Screen"</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="arrow-indicator">
|
||||
<Icon icon="ri:arrow-down-line" width="32" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.install-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 40px;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.install-card {
|
||||
text-align: center;
|
||||
max-width: 320px;
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: #000;
|
||||
border-radius: 20px;
|
||||
margin: 0 auto 24px;
|
||||
padding: 12px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.icon-wrapper img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1a1a1a;
|
||||
font-size: 28px;
|
||||
font-weight: 800;
|
||||
margin: 0 0 12px 0;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #4b5563;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
margin: 0 0 32px 0;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
text-align: left;
|
||||
background: #f3f4f6;
|
||||
padding: 20px;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.step {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
color: #374151;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.step-num {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.arrow-indicator {
|
||||
color: #3b82f6;
|
||||
animation: bounce 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0%,
|
||||
20%,
|
||||
50%,
|
||||
80%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(-10px);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -76,7 +76,7 @@
|
||||
</div>
|
||||
|
||||
{#if viewMode === "company"}
|
||||
<div class="relative max-w-[40.625rem] mx-auto mb-10">
|
||||
<div class="relative max-w-162.5 mx-auto mb-10">
|
||||
<div
|
||||
class="absolute left-6 top-1/2 -translate-y-1/2 text-white/60 flex items-center pointer-events-none"
|
||||
>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
onclick={() => openReport(report)}
|
||||
>
|
||||
<div
|
||||
class="w-16 h-16 lg:w-[4.375rem] lg:h-[4.375rem] bg-emerald-500/10 backdrop-blur-sm rounded-[1.125rem] flex items-center justify-center shrink-0 transition-all duration-300 group-hover:bg-emerald-500 group-hover:-rotate-3 group-hover:scale-105 border border-white/5 group-hover:border-emerald-400/50"
|
||||
class="w-16 h-16 lg:w-17.5 lg:h-17.5 bg-emerald-500/10 backdrop-blur-sm rounded-[1.125rem] flex items-center justify-center shrink-0 transition-all duration-300 group-hover:bg-emerald-500 group-hover:-rotate-3 group-hover:scale-105 border border-white/5 group-hover:border-emerald-400/50"
|
||||
>
|
||||
<Icon
|
||||
icon={fileDetails.icon}
|
||||
@@ -111,7 +111,7 @@
|
||||
class="text-center ml-5 lg:ml-6 group-hover:translate-x-1 transition-transform duration-300"
|
||||
>
|
||||
<div
|
||||
class="w-14 h-14 lg:w-[3.875rem] lg:h-[3.875rem] rounded-xe flex items-center justify-center mb-2 rounded-2xl shadow-lg {getScoreColor(
|
||||
class="w-14 h-14 lg:w-15.5 lg:h-15.5 rounded-xe flex items-center justify-center mb-2 rounded-2xl shadow-lg {getScoreColor(
|
||||
report.greenwashing_score,
|
||||
)} ring-4 ring-black/20"
|
||||
>
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
import { page } from "$app/stores";
|
||||
import { goto } from "$app/navigation";
|
||||
import Icon from "@iconify/svelte";
|
||||
import InstallPrompt from "$lib/components/InstallPrompt.svelte";
|
||||
|
||||
let { children } = $props();
|
||||
let isApp = $state(false);
|
||||
@@ -39,7 +38,7 @@
|
||||
function handleCameraClose() {
|
||||
isCameraActive = false;
|
||||
// Dispatch event to notify MobileHomePage to refresh
|
||||
window.dispatchEvent(new CustomEvent('scan-complete'));
|
||||
window.dispatchEvent(new CustomEvent("scan-complete"));
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@@ -94,8 +93,6 @@
|
||||
<link rel="icon" href="/ethix-logo.png" />
|
||||
</svelte:head>
|
||||
|
||||
<InstallPrompt />
|
||||
|
||||
{#if isMobile}
|
||||
<div class="mobile-container">
|
||||
<main class="app-container">
|
||||
|
||||
Reference in New Issue
Block a user