Eco-Try-webapp / templates /tryon.html
EcoTry's picture
Upload 11 files
9fb744d verified
Raw
History Blame Contribute Delete
7.42 kB
{% extends "_layout.html" %}
{% block title %}Try-On — {{ product.product_name }}{% endblock %}
{% block head %}
<style>
.tryon-wrap {
max-width: 900px;
margin: 30px auto;
padding: 0 16px;
}
/* ── Product card ── */
.product-card {
background: rgba(255,255,255,0.04);
border: 1px solid rgba(255,255,255,0.10);
border-radius: 20px;
padding: 28px;
display: flex;
gap: 32px;
align-items: flex-start;
flex-wrap: wrap;
}
.product-img-box {
flex: 0 0 260px;
background: rgba(0,0,0,0.25);
border-radius: 16px;
border: 1px solid rgba(255,255,255,0.08);
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
min-height: 280px;
}
.product-img-box img {
max-width: 100%;
max-height: 260px;
object-fit: contain;
filter: drop-shadow(0 10px 20px rgba(0,0,0,0.4));
}
.product-info { flex: 1; min-width: 220px; }
.product-info h2 {
font-size: 22px;
font-weight: 900;
margin: 0 0 8px;
}
.product-info p {
font-size: 13px;
color: var(--muted);
margin: 0 0 24px;
}
/* ── Method cards ── */
.method-row {
display: flex;
gap: 14px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.method-card {
flex: 1;
min-width: 180px;
border: 2px solid rgba(255,255,255,0.10);
border-radius: 16px;
padding: 20px 16px;
text-align: center;
cursor: pointer;
transition: border-color .15s, background .15s;
background: rgba(255,255,255,0.02);
position: relative;
}
.method-card:hover {
border-color: rgba(123,220,59,0.45);
background: rgba(123,220,59,0.05);
}
.method-card.selected {
border-color: rgba(123,220,59,0.7);
background: rgba(123,220,59,0.08);
}
.method-icon { font-size: 32px; margin-bottom: 8px; }
.method-title { font-size: 14px; font-weight: 800; }
.method-sub { font-size: 11px; color: var(--muted); margin-top: 4px; }
/* hidden file input inside upload card */
.method-card input[type="file"] {
position: absolute;
inset: 0;
opacity: 0;
cursor: pointer;
width: 100%;
height: 100%;
}
/* selected file name */
#file-name {
font-size: 12px;
color: rgba(123,220,59,0.9);
margin-top: 6px;
min-height: 16px;
}
/* ── Buttons ── */
.btn-tryon {
width: 100%;
padding: 14px;
border-radius: 14px;
border: none;
font-size: 15px;
font-weight: 800;
cursor: pointer;
background: rgba(123,220,59,0.9);
color: #000;
transition: opacity .15s;
margin-top: 4px;
}
.btn-tryon:hover { opacity: .85; }
.btn-tryon:disabled { opacity: .4; cursor: not-allowed; }
.btn-camera {
display: block;
width: 100%;
padding: 13px;
border-radius: 14px;
border: 1px solid rgba(255,255,255,0.12);
background: rgba(255,255,255,0.04);
color: rgba(255,255,255,0.85);
font-size: 14px;
font-weight: 700;
text-align: center;
text-decoration: none;
margin-top: 10px;
transition: background .15s;
}
.btn-camera:hover { background: rgba(255,255,255,0.08); }
/* ── Flash messages ── */
.flash-error {
background: rgba(255,80,80,0.10);
border: 1px solid rgba(255,80,80,0.30);
border-radius: 12px;
padding: 12px 16px;
color: #ff8080;
font-size: 13px;
margin-bottom: 16px;
}
/* ── Result ── */
.result-card {
background: rgba(255,255,255,0.04);
border: 1px solid rgba(123,220,59,0.25);
border-radius: 20px;
padding: 24px;
margin-top: 20px;
text-align: center;
}
.result-card h3 {
font-size: 16px;
font-weight: 800;
margin: 0 0 16px;
color: rgba(123,220,59,0.9);
}
.result-card img {
max-width: 100%;
max-height: 500px;
border-radius: 14px;
border: 1px solid rgba(255,255,255,0.10);
object-fit: contain;
}
.preview-thumb {
max-height: 120px;
border-radius: 10px;
margin-top: 10px;
border: 1px solid rgba(255,255,255,0.10);
display: none;
}
.loading-msg {
display: none;
color: rgba(123,220,59,0.8);
font-size: 13px;
margin-top: 10px;
text-align: center;
}
</style>
{% endblock %}
{% block body %}
<div class="tryon-wrap">
{% with messages = get_flashed_messages(with_categories=true) %}
{% for cat, msg in messages %}
<div class="flash-error">⚠️ {{ msg }}</div>
{% endfor %}
{% endwith %}
<div class="product-card">
<!-- Left: cloth image -->
<div class="product-img-box">
<img src="{{ product.image_src }}" alt="{{ product.product_name }}">
</div>
<!-- Right: try-on controls -->
<div class="product-info">
<h2>{{ product.product_name }}</h2>
<p>Choose how you want to try this on:</p>
<!-- Upload form -->
<form method="POST"
enctype="multipart/form-data"
action="{{ url_for('tryon_product', product_id=product.product_id) }}"
id="tryon-form"
onsubmit="showLoading()">
<div class="method-row">
<!-- Option 1: Upload photo -->
<div class="method-card" id="upload-card">
<input type="file"
name="person_image"
id="person_image"
accept="image/*"
onchange="onFileSelected(this)">
<div class="method-icon">📁</div>
<div class="method-title">Upload Photo</div>
<div class="method-sub">Select from your device</div>
<div id="file-name"></div>
<img id="preview-thumb" class="preview-thumb" alt="preview">
</div>
</div>
<button class="btn-tryon" type="submit" id="btn-submit" disabled>
👗 Try On with Uploaded Photo
</button>
<div class="loading-msg" id="loading-msg">
⏳ Processing your try-on… this may take 20–40 seconds
</div>
</form>
<!-- Live camera (separate link, no form needed) -->
<a class="btn-camera"
href="{{ url_for('live_tryon_page', product_id=product.product_id) }}">
📷 Try On with Live Camera
</a>
</div>
</div>
<!-- Result -->
{% if result_image_url %}
<div class="result-card">
<h3>✅ Try-On Result</h3>
<img src="{{ result_image_url }}" alt="Try-On Result">
</div>
{% endif %}
</div>
<script>
function onFileSelected(input) {
const fileName = input.files[0]?.name;
const fileNameEl = document.getElementById("file-name");
const submitBtn = document.getElementById("btn-submit");
const preview = document.getElementById("preview-thumb");
const card = document.getElementById("upload-card");
if (input.files[0]) {
fileNameEl.textContent = "✅ " + fileName;
submitBtn.disabled = false;
card.classList.add("selected");
// Show image preview
const reader = new FileReader();
reader.onload = e => {
preview.src = e.target.result;
preview.style.display = "block";
};
reader.readAsDataURL(input.files[0]);
}
}
function showLoading() {
document.getElementById("btn-submit").disabled = true;
document.getElementById("btn-submit").textContent = "⏳ Processing…";
document.getElementById("loading-msg").style.display = "block";
}
</script>
{% endblock %}