Files
foodlinkk-command-center/cockpit/templates/packaging.html
T
Aissa 5d60d33db1 Platform bundle: marketing publish, IT ops, packaging, agents mesh.
Volledige Foodlinkk Command Center uitbreiding met social automatisering,
reclamefolder filters, Proxmox monitoring en documentatie.
2026-06-09 00:41:27 +00:00

154 lines
5.9 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Packaging Studio · Foodlinkk{% endblock %}
{% block extra_head %}
<style>
.pack-grid { display: grid; grid-template-columns: 1fr 340px; gap: 1rem; }
@media (max-width: 1024px) { .pack-grid { grid-template-columns: 1fr; } }
.pack-preview {
min-height: 460px;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(circle at top, rgba(0,229,255,.08), rgba(0,0,0,.35));
border: 1px solid rgba(0,229,255,.2);
border-radius: 12px;
overflow: auto;
padding: 1rem;
}
.pack-preview svg { width: 100%; max-height: 72vh; }
.pack-tools { display:flex; gap:.5rem; flex-wrap:wrap; margin-top:.75rem; }
.elements-grid { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:.5rem; }
.project-list { max-height: 260px; overflow: auto; display:flex; flex-direction:column; gap:.5rem; }
.project-item { border:1px solid rgba(148,163,184,.15); border-radius:10px; padding:.6rem; background:rgba(0,0,0,.25); }
.project-item small { color: var(--text-secondary); display:block; margin-top:.25rem; }
</style>
{% endblock %}
{% block content %}
<div x-data="packagingStudio()" x-init="init()">
<header class="page-header">
<h1>Packaging Studio</h1>
<p class="subtitle page-tip">Foodlinkk branded box, wrap en labels met live SVG preview.</p>
</header>
<div class="pack-grid">
<section class="panel">
<div style="display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.75rem;">
<label>Type
<select class="form-input" x-model="form.type">
<option value="folding_box">Folding box</option>
<option value="wrap">Wrap</option>
<option value="round_label">Round label</option>
</select>
</label>
<label>Barcode value
<input class="form-input" x-model="form.barcode_value" placeholder="8710000000012" />
</label>
<label>Breedte (mm)<input type="number" class="form-input" x-model.number="form.width_mm" min="10" /></label>
<label>Hoogte (mm)<input type="number" class="form-input" x-model.number="form.height_mm" min="10" /></label>
<label>Diepte (mm)<input type="number" class="form-input" x-model.number="form.depth_mm" min="0" /></label>
</div>
<h2 style="font-size:1rem;margin:1rem 0 .5rem;">Elementen</h2>
<div class="elements-grid">
<label><input type="checkbox" x-model="form.elements.barcode"> Barcode</label>
<label><input type="checkbox" x-model="form.elements.logo_area"> Logo area</label>
<label><input type="checkbox" x-model="form.elements.fold_lines"> Fold lines</label>
<label><input type="checkbox" x-model="form.elements.cut_lines"> Cut lines</label>
</div>
<div class="pack-tools">
<button class="btn btn-primary" @click="generate()" :disabled="loading">
<span x-show="!loading">Genereer verpakking</span>
<span x-show="loading">Genereren…</span>
</button>
<a class="btn btn-ghost" :href="downloadUrl('svg')" x-show="projectId">Download SVG</a>
<a class="btn btn-ghost" :href="downloadUrl('png')" x-show="projectId">Download PNG</a>
<a class="btn btn-ghost" :href="downloadUrl('pdf')" x-show="projectId">Download PDF</a>
</div>
</section>
<aside class="panel">
<h2 style="font-size:1rem;margin:0 0 .75rem;">Recente projecten</h2>
<div class="project-list">
<template x-for="p in projects" :key="p.id">
<div class="project-item">
<strong x-text="p.spec.type"></strong>
<small x-text="p.spec.width_mm + '×' + p.spec.height_mm + '×' + p.spec.depth_mm + ' mm'"></small>
<small x-text="(p.created_at || '').replace('T',' ').slice(0,19)"></small>
<button class="btn btn-ghost" style="margin-top:.4rem;" @click="loadProject(p.id)">Open</button>
</div>
</template>
<p class="page-tip" x-show="!projects.length">Nog geen packaging projecten.</p>
</div>
</aside>
</div>
<div class="panel" style="margin-top:1rem;">
<div class="pack-preview">
<div x-show="svg" x-html="svg"></div>
<p class="page-tip" x-show="!svg && !loading">Start met Genereren om de preview te zien.</p>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
function packagingStudio() {
return {
loading: false,
svg: '',
projectId: '',
projects: [],
form: {
type: 'folding_box',
width_mm: 120,
height_mm: 80,
depth_mm: 40,
barcode_value: '8710000000012',
brand: {},
elements: { barcode: true, logo_area: true, fold_lines: true, cut_lines: true }
},
async init() { await this.refreshProjects(); },
downloadUrl(format) {
if (!this.projectId) return '#';
return '/api/packaging/download/' + this.projectId + '?format=' + format;
},
async refreshProjects() {
try {
const r = await Cockpit.api('/api/packaging/projects?limit=20');
this.projects = r.items || [];
} catch (e) {
this.projects = [];
}
},
async loadProject(id) {
this.projectId = id;
try {
const data = await fetch('/api/packaging/download/' + id + '?format=svg').then(x => x.text());
this.svg = data;
} catch (e) {
Cockpit.toast('Kon project niet laden', 'error');
}
},
async generate() {
if (this.loading) return;
this.loading = true;
try {
const r = await Cockpit.api('/api/packaging/generate', {
method: 'POST',
body: JSON.stringify(this.form)
});
this.svg = r.svg || '';
this.projectId = r.id || '';
await this.refreshProjects();
Cockpit.toast('Packaging gegenereerd', 'success');
} catch (e) {
Cockpit.toast(e.message || 'Genereren mislukt', 'error');
}
this.loading = false;
}
};
}
</script>
{% endblock %}