|
|
<!doctype html> |
|
|
<html lang="fr"> |
|
|
<head> |
|
|
<meta charset="UTF-8" /> |
|
|
<meta |
|
|
name="viewport" |
|
|
content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover" |
|
|
/> |
|
|
<title>{% block title %}{% endblock %} - {{ app_name }}</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link |
|
|
rel="stylesheet" |
|
|
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" |
|
|
/> |
|
|
|
|
|
|
|
|
<script> |
|
|
tailwind.config = { |
|
|
theme: { |
|
|
extend: { |
|
|
fontFamily: { |
|
|
sans: ["DM Sans", "sans-serif"], |
|
|
}, |
|
|
colors: { |
|
|
bg: "#111827", |
|
|
card: "#1F2937", |
|
|
cardLight: "#374151", |
|
|
primary: "#10B981", |
|
|
primaryDark: "#059669", |
|
|
accent: "#FBBF24", |
|
|
danger: "#EF4444", |
|
|
textMuted: "#9CA3AF", |
|
|
}, |
|
|
boxShadow: { |
|
|
glow: "0 0 20px rgba(16, 185, 129, 0.15)", |
|
|
float: "0 10px 30px -10px rgba(0, 0, 0, 0.5)", |
|
|
}, |
|
|
animation: { |
|
|
pop: "pop 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)", |
|
|
"slide-up": "slideUp 0.3s ease-out", |
|
|
}, |
|
|
keyframes: { |
|
|
pop: { |
|
|
"0%": { transform: "scale(0.95)" }, |
|
|
"100%": { transform: "scale(1)" }, |
|
|
}, |
|
|
slideUp: { |
|
|
"0%": { transform: "translateY(100%)" }, |
|
|
"100%": { transform: "translateY(0)" }, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}, |
|
|
}; |
|
|
</script> |
|
|
<link |
|
|
href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap" |
|
|
rel="stylesheet" |
|
|
/> |
|
|
|
|
|
<style> |
|
|
body { |
|
|
font-family: "DM Sans", sans-serif; |
|
|
background-color: #111827; |
|
|
color: white; |
|
|
-webkit-tap-highlight-color: transparent; |
|
|
} |
|
|
|
|
|
|
|
|
.no-scrollbar::-webkit-scrollbar { |
|
|
display: none; |
|
|
} |
|
|
|
|
|
|
|
|
.btn-press:active { |
|
|
transform: scale(0.96); |
|
|
transition: transform 0.1s; |
|
|
} |
|
|
|
|
|
|
|
|
.nav-link.active { |
|
|
color: white; |
|
|
} |
|
|
.nav-link.active i { |
|
|
color: #fbbf24; |
|
|
transform: translateY(-2px); |
|
|
} |
|
|
|
|
|
|
|
|
#toast-box { |
|
|
position: fixed; |
|
|
top: 20px; |
|
|
left: 50%; |
|
|
transform: translateX(-50%); |
|
|
z-index: 100; |
|
|
width: 90%; |
|
|
max-width: 400px; |
|
|
pointer-events: none; |
|
|
} |
|
|
.toast { |
|
|
background: #374151; |
|
|
color: white; |
|
|
padding: 12px 16px; |
|
|
border-radius: 12px; |
|
|
margin-bottom: 8px; |
|
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3); |
|
|
display: flex; |
|
|
align-items: center; |
|
|
gap: 12px; |
|
|
border-left: 4px solid; |
|
|
animation: slideDown 0.3s; |
|
|
pointer-events: auto; |
|
|
} |
|
|
@keyframes slideDown { |
|
|
from { |
|
|
opacity: 0; |
|
|
transform: translateY(-20px); |
|
|
} |
|
|
to { |
|
|
opacity: 1; |
|
|
transform: translateY(0); |
|
|
} |
|
|
} |
|
|
</style> |
|
|
{% block extra_css %}{% endblock %} |
|
|
</head> |
|
|
<body class="overflow-x-hidden"> |
|
|
|
|
|
<div id="toast-box"></div> |
|
|
|
|
|
|
|
|
{% if current_user.is_authenticated %} |
|
|
<header |
|
|
class="px-6 pt-8 pb-4 flex justify-between items-center bg-bg sticky top-0 z-30" |
|
|
> |
|
|
<div class="flex flex-col"> |
|
|
<span |
|
|
class="text-textMuted text-xs font-bold uppercase tracking-wider" |
|
|
>Espace Membre</span |
|
|
> |
|
|
<span class="text-xl font-bold text-white tracking-tight" |
|
|
>Apex Ores<span class="text-accent">.</span></span |
|
|
> |
|
|
</div> |
|
|
<a |
|
|
href="{{ url_for('main.referral') }}" |
|
|
class="w-10 h-10 bg-card rounded-full flex items-center justify-center border border-gray-700 cursor-pointer hover:border-accent transition" |
|
|
> |
|
|
<span class="font-bold text-gray-300 text-sm"> |
|
|
{% if current_user.name %} {{ current_user.name[:2].upper() |
|
|
}} {% else %} U {% endif %} |
|
|
</span> |
|
|
</a> |
|
|
</header> |
|
|
{% endif %} |
|
|
|
|
|
|
|
|
<div class="px-5 mt-4"> |
|
|
{% with messages = get_flashed_messages(with_categories=true) %} {% |
|
|
if messages %} {% for category, message in messages %} |
|
|
<div |
|
|
class="mb-4 p-4 rounded-xl flex items-center gap-3 animate-pop {% if category == 'success' %}bg-primary/10 border-l-4 border-primary text-primary{% elif category == 'error' %}bg-danger/10 border-l-4 border-danger text-danger{% else %}bg-cardLight border-l-4 border-accent text-accent{% endif %}" |
|
|
> |
|
|
<i |
|
|
class="fa-solid {% if category == 'success' %}fa-circle-check{% elif category == 'error' %}fa-circle-xmark{% else %}fa-circle-info{% endif %}" |
|
|
></i> |
|
|
<p class="text-sm font-medium">{{ message }}</p> |
|
|
</div> |
|
|
{% endfor %} {% endif %} {% endwith %} |
|
|
</div> |
|
|
|
|
|
|
|
|
<main class="pb-32">{% block content %}{% endblock %}</main> |
|
|
|
|
|
|
|
|
{% if current_user.is_authenticated %} |
|
|
<nav |
|
|
class="fixed bottom-6 left-4 right-4 h-16 bg-card/90 backdrop-blur-xl border border-gray-700/50 rounded-full shadow-float z-40 px-2 flex justify-between items-center max-w-md mx-auto" |
|
|
> |
|
|
<a |
|
|
href="{{ url_for('main.dashboard') }}" |
|
|
class="nav-link flex-1 h-full flex flex-col items-center justify-center gap-1 text-gray-500 transition-colors {% if request.endpoint == 'main.dashboard' %}active{% endif %}" |
|
|
> |
|
|
<i class="fa-solid fa-house text-lg"></i> |
|
|
<span class="text-[10px] font-medium">Accueil</span> |
|
|
</a> |
|
|
|
|
|
<a |
|
|
href="{{ url_for('main.notifications') }}" |
|
|
class="nav-link flex-1 h-full flex flex-col items-center justify-center gap-1 text-gray-500 transition-colors {% if request.endpoint == 'main.notifications' %}active{% endif %}" |
|
|
> |
|
|
<i class="fa-solid fa-clock-rotate-left text-lg"></i> |
|
|
<span class="text-[10px] font-medium">Notifs</span> |
|
|
</a> |
|
|
|
|
|
|
|
|
<div class="relative w-16 flex justify-center"> |
|
|
<a |
|
|
href="{{ url_for('main.market') }}" |
|
|
class="absolute -top-6 w-14 h-14 bg-accent text-gray-900 rounded-full flex items-center justify-center shadow-lg shadow-amber-500/30 border-4 border-bg transform active:scale-95 transition-transform" |
|
|
> |
|
|
<i class="fa-solid fa-cart-shopping text-xl"></i> |
|
|
</a> |
|
|
</div> |
|
|
|
|
|
<div |
|
|
class="flex-1 h-full flex flex-col items-center justify-center gap-1 text-gray-500" |
|
|
> |
|
|
<span class="text-[10px] font-medium mt-6">Marché</span> |
|
|
</div> |
|
|
|
|
|
<a |
|
|
href="{{ url_for('main.referral') }}" |
|
|
class="nav-link flex-1 h-full flex flex-col items-center justify-center gap-1 text-gray-500 transition-colors {% if request.endpoint == 'main.referral' %}active{% endif %}" |
|
|
> |
|
|
<i class="fa-solid fa-user text-lg"></i> |
|
|
<span class="text-[10px] font-medium">Profil</span> |
|
|
</a> |
|
|
</nav> |
|
|
{% endif %} |
|
|
|
|
|
<script> |
|
|
function showToast(message, type = "info") { |
|
|
const box = document.getElementById("toast-box"); |
|
|
const toast = document.createElement("div"); |
|
|
toast.className = "toast"; |
|
|
|
|
|
let color = |
|
|
type === "error" |
|
|
? "#EF4444" |
|
|
: type === "success" |
|
|
? "#10B981" |
|
|
: "#FBBF24"; |
|
|
let icon = |
|
|
type === "error" |
|
|
? "fa-circle-xmark" |
|
|
: type === "success" |
|
|
? "fa-circle-check" |
|
|
: "fa-info-circle"; |
|
|
|
|
|
toast.style.borderColor = color; |
|
|
toast.innerHTML = `<i class="fa-solid ${icon}" style="color:${color}"></i> <span>${message}</span>`; |
|
|
|
|
|
box.appendChild(toast); |
|
|
setTimeout(() => { |
|
|
toast.style.opacity = "0"; |
|
|
toast.style.transform = "translateY(-20px)"; |
|
|
setTimeout(() => toast.remove(), 300); |
|
|
}, 3000); |
|
|
} |
|
|
</script> |
|
|
{% block extra_js %}{% endblock %} |
|
|
</body> |
|
|
</html> |
|
|
|