Initial commit: existing turf_saas codebase
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
305
portail.html
Executable file
305
portail.html
Executable file
@@ -0,0 +1,305 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🐾 H3R7Tech - Portail</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%); min-height: 100vh; color: #eee; }
|
||||
|
||||
/* Header */
|
||||
header { background: linear-gradient(90deg, #1a1a2e, #0f3460); padding: 30px 20px; text-align: center; border-bottom: 2px solid #00d9ff; }
|
||||
header h1 { font-size: 42px; background: linear-gradient(90deg, #00d9ff, #e94560); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 10px; }
|
||||
header p { color: #888; font-size: 16px; }
|
||||
|
||||
/* Categories */
|
||||
.categories { display: flex; justify-content: center; gap: 15px; padding: 25px 20px; flex-wrap: wrap; background: rgba(0,0,0,0.2); }
|
||||
.cat-btn { padding: 12px 25px; background: #16213e; border: 1px solid #30363d; border-radius: 8px; color: #c9d1d9; cursor: pointer; transition: all 0.3s; text-decoration: none; }
|
||||
.cat-btn:hover, .cat-btn.active { background: #00d9ff; color: #0f0f23; border-color: #00d9ff; }
|
||||
|
||||
/* Links */
|
||||
.links { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; padding: 30px; max-width: 1400px; margin: 0 auto; }
|
||||
.link-card { background: #161b22; border: 1px solid #30363d; border-radius: 12px; padding: 20px; transition: all 0.3s; text-decoration: none; color: inherit; }
|
||||
.link-card:hover { transform: translateY(-5px); border-color: #00d9ff; box-shadow: 0 10px 30px rgba(0,217,255,0.1); }
|
||||
.link-card h3 { font-size: 18px; margin-bottom: 8px; color: #00d9ff; }
|
||||
.link-card p { font-size: 13px; color: #8b949e; }
|
||||
.link-card .badge { display: inline-block; padding: 3px 8px; border-radius: 4px; font-size: 11px; margin-top: 10px; }
|
||||
.badge.ok { background: rgba(63,185,80,0.2); color: #3fb950; }
|
||||
.badge.warn { background: rgba(210,153,34,0.2); color: #d29922; }
|
||||
|
||||
/* Footer */
|
||||
footer { text-align: center; padding: 30px; color: #666; font-size: 14px; }
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.links { grid-template-columns: 1fr; padding: 15px; }
|
||||
header h1 { font-size: 28px; }
|
||||
.search-bar { flex-direction: column; }
|
||||
}
|
||||
|
||||
.home-btn{position:fixed;top:10px;left:10px;z-index:9999;background:linear-gradient(135deg,#00d9ff,#7b2cbf);color:#fff;border:none;border-radius:8px;padding:10px 15px;font-size:14px;cursor:pointer;text-decoration:none;display:flex;align-items:center;gap:8px;box-shadow:0 2px 10px rgba(0,217,255,0.3);transition:all 0.3s;font-family:-apple-system,BlinkMacSystemFont,sans-serif}.home-btn:hover{transform:translateY(-2px);box-shadow:0 4px 15px rgba(0,217,255,0.5)}
|
||||
|
||||
/* Brave Search Zone */
|
||||
.search-zone { padding: 20px 30px 10px; max-width: 860px; margin: 0 auto; width: 100%; }
|
||||
.search-zone-title { font-size: 13px; color: #555; text-align: center; margin-bottom: 10px; letter-spacing: 0.5px; text-transform: uppercase; }
|
||||
.search-bar { display: flex; gap: 8px; }
|
||||
.search-bar input { flex: 1; padding: 12px 16px; background: #161b22; border: 1px solid #30363d; border-radius: 8px; color: #eee; font-size: 14px; outline: none; transition: border-color 0.2s; }
|
||||
.search-bar input:focus { border-color: #00d9ff; box-shadow: 0 0 0 2px rgba(0,217,255,0.1); }
|
||||
.search-bar input::placeholder { color: #555; }
|
||||
.search-bar select { padding: 12px 10px; background: #161b22; border: 1px solid #30363d; border-radius: 8px; color: #888; font-size: 13px; outline: none; cursor: pointer; }
|
||||
.search-bar select:focus { border-color: #00d9ff; }
|
||||
.search-bar button { padding: 12px 22px; background: linear-gradient(135deg, #00d9ff, #7b2cbf); border: none; border-radius: 8px; color: #fff; font-size: 14px; font-weight: 600; cursor: pointer; transition: opacity 0.2s; white-space: nowrap; }
|
||||
.search-bar button:hover { opacity: 0.85; }
|
||||
.search-bar button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
.search-results { margin-top: 14px; display: none; }
|
||||
.search-results.visible { display: block; }
|
||||
.search-result-item { background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 14px 16px; margin-bottom: 10px; transition: border-color 0.2s; }
|
||||
.search-result-item:hover { border-color: #00d9ff; }
|
||||
.search-result-item a { color: #00d9ff; text-decoration: none; font-size: 15px; font-weight: 600; }
|
||||
.search-result-item a:hover { text-decoration: underline; }
|
||||
.search-result-item .result-url { font-size: 11px; color: #555; margin: 4px 0 6px; word-break: break-all; }
|
||||
.search-result-item .result-desc { font-size: 13px; color: #8b949e; line-height: 1.5; }
|
||||
.search-result-item .result-meta { font-size: 11px; color: #444; margin-top: 6px; display: flex; gap: 12px; }
|
||||
.search-status { text-align: center; padding: 12px; color: #888; font-size: 13px; }
|
||||
.search-error { color: #e94560; font-size: 13px; text-align: center; padding: 8px; background: rgba(233,69,96,0.08); border-radius: 6px; margin-top: 8px; }
|
||||
.search-count { font-size: 12px; color: #555; margin-bottom: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a href="https://portal-kolifee.duckdns.org/" class="home-btn" title="Retour au portail"><span style="font-size:18px">🏠</span><span>Accueil</span></a>
|
||||
<header>
|
||||
<h1>🐾 H3R7Tech</h1>
|
||||
<p>Portail des services & applications</p>
|
||||
</header>
|
||||
|
||||
<!-- BRAVE SEARCH ZONE -->
|
||||
<div class="search-zone">
|
||||
<div class="search-zone-title">🔍 Brave Search — Recherche web intégrée</div>
|
||||
<div class="search-bar">
|
||||
<input type="text" id="searchInput" placeholder="Rechercher sur le web..." autocomplete="off" />
|
||||
<select id="searchType">
|
||||
<option value="web">Web</option>
|
||||
<option value="news">Actualités</option>
|
||||
</select>
|
||||
<button id="searchBtn" onclick="doSearch()">Rechercher</button>
|
||||
</div>
|
||||
<div id="searchResults" class="search-results"></div>
|
||||
</div>
|
||||
|
||||
<div class="categories">
|
||||
<a href="#all" class="cat-btn active">Tous</a>
|
||||
<a href="#business" class="cat-btn">Business</a>
|
||||
<a href="#tools" class="cat-btn">Outils</a>
|
||||
<a href="#templates" class="cat-btn">Templates</a>
|
||||
<a href="#poc" class="cat-btn">POC</a>
|
||||
</div>
|
||||
|
||||
<div class="links">
|
||||
<!-- BUSINESS -->
|
||||
<a href="/crm/" class="link-card" data-category="business">
|
||||
<h3>📊 CRM Prospects</h3>
|
||||
<p>Gestion des prospects artisans, boulangeries, garages</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/depenses/" class="link-card" data-category="business">
|
||||
<h3>💰 Dépenses Trello</h3>
|
||||
<p>Suivi des dépenses avec export Trello</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/business" class="link-card" data-category="business">
|
||||
<h3>💼 Discord Leads</h3>
|
||||
<p>Dashboard leads Discord - Analyse automatique</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/pod/pod_manager.html" class="link-card" data-category="business">
|
||||
<h3>📦 POD Manager</h3>
|
||||
<p>Gestion Print on Demand - Designs, produits, ventes</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/pod/niches_business.html" class="link-card" data-category="business">
|
||||
<h3>🎨 Guide Niches POD</h3>
|
||||
<p>Analyse des 6 niches POD rentables</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<!-- PROMPTS -->
|
||||
<a href="/prompts" class="link-card" data-category="tools">
|
||||
<h3>📝 Prompts IA</h3>
|
||||
<p>Catalogue de prompts par profession - Juriste, Graphiste, Commercial...</p>
|
||||
<span class="badge ok">✅ 110+</span>
|
||||
</a>
|
||||
|
||||
<!-- SKILLS -->
|
||||
<a href="/skills" class="link-card" data-category="tools">
|
||||
<h3>🤖 Agent AI Skills</h3>
|
||||
<p>Base de connaissances de skills pour agents IA</p>
|
||||
<span class="badge ok">✅ Nouveau</span>
|
||||
</a>
|
||||
|
||||
<a href="/agent-ia" class="link-card" data-category="tools">
|
||||
<h3>🧠 Agent IA</h3>
|
||||
<p>Chat multi-workflows avec historique persistant</p>
|
||||
<span class="badge ok">✅ Nouveau</span>
|
||||
</a>
|
||||
|
||||
<!-- TURF -->
|
||||
<a href="/turf/" class="link-card" data-category="tools">
|
||||
<h3>🏇 Turf Dashboard</h3>
|
||||
<p>Analyses et prédictions courses hippiques</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<!-- MAP -->
|
||||
<a href="/map" class="link-card" data-category="tools">
|
||||
<h3>🗺️ Cartographie Projets</h3>
|
||||
<p>Visualisation des 12 projets H3R7Tech - Architecture et status</p>
|
||||
<span class="badge ok">✅ Nouveau</span>
|
||||
</a>
|
||||
|
||||
<!-- DOCS -->
|
||||
<a href="/boite_a_idees.html" class="link-card" data-category="tools">
|
||||
<h3>💡 Boîte à Idées</h3>
|
||||
<p>Suivi de tous les Projets H3R7Tech</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/gitea/" class="link-card" data-category="tools">
|
||||
<h3>🔧 Gitea (Git)</h3>
|
||||
<p>Dépôt de code (accès privé requis)</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
|
||||
<a href="/datagouv_explorer.html" class="link-card" data-category="tools">
|
||||
<h3>📂 Data.gouv.fr Explorer</h3>
|
||||
<p>Explorer les datasets ouverts de l'administration française</p>
|
||||
<span class="badge ok">✅ Nouveau</span>
|
||||
</a>
|
||||
|
||||
<a href="/api_datagouv_reference.html" class="link-card" data-category="tools">
|
||||
<h3>📡 API Data.gouv.fr</h3>
|
||||
<p>Référence complète des endpoints de l'API</p>
|
||||
<span class="badge ok">✅ Nouveau</span>
|
||||
</a>
|
||||
|
||||
<!-- TEMPLATES -->
|
||||
<a href="/template_restaurant_json.html" class="link-card" data-category="templates">
|
||||
<h3>🍽️ Template Restaurant</h3>
|
||||
<p>Site web pour restaurant</p>
|
||||
<span class="badge ok">✅</span>
|
||||
</a>
|
||||
|
||||
<a href="/template_boulangerie_final.html" class="link-card" data-category="templates">
|
||||
<h3>🥖 Template Boulangerie</h3>
|
||||
<p>Site web pour boulangerie</p>
|
||||
<span class="badge ok">✅</span>
|
||||
</a>
|
||||
|
||||
<a href="/template_artisan_final.html" class="link-card" data-category="templates">
|
||||
<h3>🔨 Template Artisan</h3>
|
||||
<p>Site web pour artisan</p>
|
||||
<span class="badge ok">✅</span>
|
||||
</a>
|
||||
|
||||
<!-- POC -->
|
||||
<a href="/candidatures/crm_candidatures.html" class="link-card" data-category="poc">
|
||||
<h3>📋 CRM Candidatures</h3>
|
||||
<p>Kanban des candidatures</p>
|
||||
<span class="badge ok">✅ Opérationnel</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>H3R7Tech Portal | Dernière mise à jour: 25/04/2026 | Brave Search & Email Resend intégrés</p>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// Simple filter
|
||||
document.querySelectorAll('.cat-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
document.querySelectorAll('.cat-btn').forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
|
||||
const cat = btn.getAttribute('href').replace('#', '');
|
||||
document.querySelectorAll('.link-card').forEach(card => {
|
||||
if (cat === 'all' || card.dataset.category === cat) {
|
||||
card.style.display = 'block';
|
||||
} else {
|
||||
card.style.display = 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Brave Search integration
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const searchBtn = document.getElementById('searchBtn');
|
||||
const searchResults = document.getElementById('searchResults');
|
||||
const searchType = document.getElementById('searchType');
|
||||
|
||||
searchInput.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') doSearch();
|
||||
});
|
||||
|
||||
async function doSearch() {
|
||||
const q = searchInput.value.trim();
|
||||
if (!q) return;
|
||||
|
||||
const type = searchType.value;
|
||||
searchBtn.disabled = true;
|
||||
searchBtn.textContent = '...';
|
||||
searchResults.className = 'search-results visible';
|
||||
searchResults.innerHTML = '<div class="search-status">Recherche en cours...</div>';
|
||||
|
||||
try {
|
||||
const params = new URLSearchParams({ q, count: 10, type });
|
||||
const resp = await fetch('/api/brave-search?' + params);
|
||||
const data = await resp.json();
|
||||
|
||||
if (!resp.ok || data.error) {
|
||||
searchResults.innerHTML = `<div class="search-error">Erreur: ${data.error || 'Requête échouée'}</div>`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.results || data.results.length === 0) {
|
||||
searchResults.innerHTML = '<div class="search-status">Aucun résultat trouvé.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = `<div class="search-count">${data.count} résultat(s) pour "<strong>${escapeHtml(q)}</strong>" (${type === 'news' ? 'Actualités' : 'Web'})</div>`;
|
||||
data.results.forEach(r => {
|
||||
const source = r.source ? `<span>📰 ${escapeHtml(r.source)}</span>` : '';
|
||||
const age = r.age ? `<span>🕒 ${escapeHtml(r.age)}</span>` : '';
|
||||
html += `
|
||||
<div class="search-result-item">
|
||||
<a href="${escapeHtml(r.url)}" target="_blank" rel="noopener">${escapeHtml(r.title)}</a>
|
||||
<div class="result-url">${escapeHtml(r.url)}</div>
|
||||
${r.description ? `<div class="result-desc">${escapeHtml(r.description)}</div>` : ''}
|
||||
<div class="result-meta">${source}${age}</div>
|
||||
</div>`;
|
||||
});
|
||||
|
||||
searchResults.innerHTML = html;
|
||||
} catch (err) {
|
||||
searchResults.innerHTML = `<div class="search-error">Erreur réseau: ${escapeHtml(err.message)}</div>`;
|
||||
} finally {
|
||||
searchBtn.disabled = false;
|
||||
searchBtn.textContent = 'Rechercher';
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
if (!str) return '';
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user