Rebrand to Card Forge
This commit is contained in:
@@ -5,8 +5,8 @@ services:
|
|||||||
env_file: .env
|
env_file: .env
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.esncard-generator.rule=Host(`esncards.orebolt.cz`)"
|
- "traefik.http.routers.card-forge.rule=Host(`cardforge.orebolt.cz`)"
|
||||||
- "traefik.http.routers.esncard-generator.tls.certresolver=leresolver"
|
- "traefik.http.routers.card-forge.tls.certresolver=leresolver"
|
||||||
- "traefik.http.routers.esncard-generator.entrypoints=websecure"
|
- "traefik.http.routers.card-forge.entrypoints=websecure"
|
||||||
- "traefik.http.services.esncard-generator.loadbalancer.server.port=3000"
|
- "traefik.http.services.card-forge.loadbalancer.server.port=3000"
|
||||||
- "traefik.http.routers.esncard-generator.middlewares=hsts"
|
- "traefik.http.routers.card-forge.middlewares=hsts"
|
||||||
|
|||||||
1429
package-lock.json
generated
1429
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "esn-card-generator",
|
"name": "card-forge",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<title>ESN Card Generator</title>
|
<title>Card Forge</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|||||||
@@ -1,40 +1,59 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { currentStep } from '$lib/stores.js';
|
import { currentStep } from '$lib/stores.js';
|
||||||
|
import FeatureList from './splash/FeatureList.svelte';
|
||||||
|
|
||||||
function startWizard() {
|
function startWizard() {
|
||||||
currentStep.set(1); // Move to auth step
|
currentStep.set(1); // Move to auth step
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container mx-auto max-w-4xl p-2">
|
<div class="flex min-h-screen items-center justify-center bg-gray-100 p-4">
|
||||||
<div class="container mx-auto max-w-4xl rounded-lg bg-white p-8 text-center shadow-lg">
|
<div
|
||||||
<div class="mb-8">
|
class="container mx-auto max-w-4xl rounded-lg border border-gray-200 bg-white/90 p-10 text-center shadow-xl"
|
||||||
<!-- ESN Logo placeholder -->
|
>
|
||||||
<div class="mx-auto mb-6 flex h-48 w-48 items-center justify-center rounded-full bg-gray-400 p-6">
|
<div class="mb-10 flex flex-col items-center">
|
||||||
<img src="/favicon.svg" alt="ESN Logo" class="h-32 w-32" />
|
<!-- Animated ESN Logo -->
|
||||||
|
<div
|
||||||
|
class="mx-auto mb-6 flex h-40 w-40 items-center justify-center rounded-full bg-gradient-to-tr from-blue-400 via-purple-400 to-pink-400"
|
||||||
|
>
|
||||||
|
<img src="/favicon.svg" alt="ESN Logo" class="h-28 w-28 drop-shadow-lg" />
|
||||||
</div>
|
</div>
|
||||||
|
<h1
|
||||||
<h1 class="mb-6 text-3xl font-bold text-gray-800">ESNcard Generator</h1>
|
class="mb-2 pb-4 bg-gradient-to-r from-blue-600 via-purple-600 to-pink-600 bg-clip-text text-6xl font-extrabold tracking-tight text-transparent"
|
||||||
|
>
|
||||||
<p class="mb-4 text-lg leading-relaxed text-gray-700">
|
Card Forge
|
||||||
Transform your Google Sheets into professional ESN membership cards with photos.
|
</h1>
|
||||||
|
<p class="mb-4 text-xl leading-relaxed font-medium text-gray-700">
|
||||||
|
Transform your Google Sheets into professional ESNcards with photos.
|
||||||
</p>
|
</p>
|
||||||
|
<p class="mb-4 text-lg leading-relaxed text-gray-600">
|
||||||
<p class="mb-6 text-lg leading-relaxed text-gray-700">
|
<span class="font-semibold text-black-800"
|
||||||
Privacy-first: all processing happens in your browser.
|
>Privacy-first</span
|
||||||
|
>: all processing happens in your browser.
|
||||||
</p>
|
</p>
|
||||||
|
<div class="mb-6">
|
||||||
<div class="mb-8 text-sm text-gray-500">
|
<a
|
||||||
<p class="mb-2">✓ Import data from Google Sheets</p>
|
href="https://youtube.com"
|
||||||
<p class="mb-2">✓ Automatic face detection and cropping</p>
|
target="_blank"
|
||||||
<p class="mb-2">✓ Generate text and photo PDFs</p>
|
class="inline-flex items-center gap-2 rounded-lg bg-pink-100 px-4 py-2 font-semibold text-pink-700 transition-colors hover:bg-pink-200"
|
||||||
<p>✓ No data stored on our servers</p>
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path
|
||||||
|
d="M23.498 6.186a2.998 2.998 0 0 0-2.115-2.117C19.073 3.5 12 3.5 12 3.5s-7.073 0-9.383.569A2.998 2.998 0 0 0 .502 6.186C0 8.497 0 12 0 12s0 3.503.502 5.814a2.998 2.998 0 0 0 2.115 2.117C4.927 20.5 12 20.5 12 20.5s7.073 0 9.383-.569a2.998 2.998 0 0 0 2.115-2.117C24 15.503 24 12 24 12s0-3.503-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
Watch how Card Forge works
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
<FeatureList class="mb-8" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
on:click={startWizard}
|
onclick={startWizard}
|
||||||
class="rounded-lg bg-blue-600 px-8 py-3 font-semibold text-white transition-colors hover:bg-blue-700"
|
class="rounded-lg bg-blue-600 bg-gradient-to-r px-10 py-4 text-lg font-bold text-white shadow-lg transition-transform hover:scale-105"
|
||||||
>
|
>
|
||||||
Start Creating Cards
|
Start Creating Cards
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -26,8 +26,8 @@
|
|||||||
];
|
];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="min-h-screen bg-gray-50">
|
<div class="bg-gray-100 min-h-screen p-4">
|
||||||
<div class="container mx-auto max-w-4xl p-4">
|
<div class="container mx-auto max-w-4xl pb-10">
|
||||||
<!-- Progress indicator -->
|
<!-- Progress indicator -->
|
||||||
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
<div class="bg-white rounded-lg shadow-sm p-6 mb-6">
|
||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
|||||||
10
src/lib/components/splash/FeatureList.svelte
Normal file
10
src/lib/components/splash/FeatureList.svelte
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
// Feature list for splash page
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ul class="mb-8 text-left text-gray-700 grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||||
|
<li class="flex items-center gap-2"><span class="text-green-500 font-bold">✓</span> Import data from Google Sheets</li>
|
||||||
|
<li class="flex items-center gap-2"><span class="text-green-500 font-bold">✓</span> Automatic face detection & cropping</li>
|
||||||
|
<li class="flex items-center gap-2"><span class="text-green-500 font-bold">✓</span> Generate text & photo PDFs</li>
|
||||||
|
<li class="flex items-center gap-2"><span class="text-green-500 font-bold">✓</span> No data stored on our servers</li>
|
||||||
|
</ul>
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
console.log('Selected sheet on mount:', $selectedSheet);
|
console.log('Selected sheet on mount:', $selectedSheet);
|
||||||
|
|
||||||
// Check if we already have saved mapping data
|
// Check if we already have saved mapping data
|
||||||
const recentSheetsData = localStorage.getItem('esn-recent-sheets');
|
const recentSheetsData = localStorage.getItem('recent-sheets');
|
||||||
|
|
||||||
if (recentSheetsData) {
|
if (recentSheetsData) {
|
||||||
try {
|
try {
|
||||||
@@ -321,7 +321,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const recentSheetsKey = 'esn-recent-sheets';
|
const recentSheetsKey = 'recent-sheets';
|
||||||
const existingData = localStorage.getItem(recentSheetsKey);
|
const existingData = localStorage.getItem(recentSheetsKey);
|
||||||
|
|
||||||
if (existingData) {
|
if (existingData) {
|
||||||
@@ -392,7 +392,7 @@
|
|||||||
|
|
||||||
// Save column mapping to localStorage for the selected sheet
|
// Save column mapping to localStorage for the selected sheet
|
||||||
try {
|
try {
|
||||||
const recentSheetsKey = 'esn-recent-sheets';
|
const recentSheetsKey = 'recent-sheets';
|
||||||
const existingData = localStorage.getItem(recentSheetsKey);
|
const existingData = localStorage.getItem(recentSheetsKey);
|
||||||
let recentSheets = existingData ? JSON.parse(existingData) : [];
|
let recentSheets = existingData ? JSON.parse(existingData) : [];
|
||||||
|
|
||||||
|
|||||||
@@ -409,28 +409,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Generation Status -->
|
|
||||||
{#if isGenerating}
|
|
||||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
|
|
||||||
<div class="flex items-center justify-between mb-3">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="w-5 h-5 border-2 border-blue-600 border-t-transparent rounded-full animate-spin mr-3"></div>
|
|
||||||
<span class="text-sm text-blue-800">{progress.stage}</span>
|
|
||||||
</div>
|
|
||||||
<span class="text-sm text-blue-600">
|
|
||||||
{progress.current} / {progress.total}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="w-full bg-blue-200 rounded-full h-2">
|
|
||||||
<div
|
|
||||||
class="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
|
||||||
style="width: {(progress.current / progress.total) * 100}%"
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Summary -->
|
<!-- Summary -->
|
||||||
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 mb-6">
|
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4 mb-6">
|
||||||
<h3 class="text-sm font-medium text-gray-700 mb-3">Generation Summary</h3>
|
<h3 class="text-sm font-medium text-gray-700 mb-3">Generation Summary</h3>
|
||||||
@@ -456,6 +434,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Generation Status -->
|
||||||
|
{#if isGenerating}
|
||||||
|
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
|
||||||
|
<div class="flex items-center justify-between mb-3">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-5 h-5 border-2 border-blue-600 border-t-transparent rounded-full animate-spin mr-3"></div>
|
||||||
|
<span class="text-sm text-blue-800">{progress.stage}</span>
|
||||||
|
</div>
|
||||||
|
<span class="text-sm text-blue-600">
|
||||||
|
{progress.current} / {progress.total}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full bg-blue-200 rounded-full h-2">
|
||||||
|
<div
|
||||||
|
class="bg-blue-600 h-2 rounded-full transition-all duration-300"
|
||||||
|
style="width: {(progress.current / progress.total) * 100}%"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<!-- Generate Button -->
|
<!-- Generate Button -->
|
||||||
{#if !isGenerating && generatedFiles.length === 0}
|
{#if !isGenerating && generatedFiles.length === 0}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
let hasSearched = $state(false);
|
let hasSearched = $state(false);
|
||||||
let recentSheets = $state<any[]>([]);
|
let recentSheets = $state<any[]>([]);
|
||||||
|
|
||||||
const RECENT_SHEETS_KEY = 'esn-recent-sheets';
|
const RECENT_SHEETS_KEY = 'recent-sheets';
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
loadRecentSheets();
|
loadRecentSheets();
|
||||||
|
|||||||
Reference in New Issue
Block a user