183 lines
7.6 KiB
HTML
183 lines
7.6 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>SWOT Analysis</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script
|
|
src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.js"
|
|
integrity="sha384-oeUn82QNXPuVkGCkcrInrS1twIxKhkZiFfr2TdiuObZ3n3yIeMiqcRzkIcguaof1"
|
|
crossorigin="anonymous"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
animation: {
|
|
"fade-in": "fadeIn 0.5s ease-in-out",
|
|
"pulse-slow": "pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
|
float: "float 6s ease-in-out infinite",
|
|
},
|
|
keyframes: {
|
|
fadeIn: {
|
|
"0%": { opacity: "0", transform: "translateY(10px)" },
|
|
"100%": { opacity: "1", transform: "translateY(0)" },
|
|
},
|
|
float: {
|
|
"0%, 100%": { transform: "translateY(0)" },
|
|
"50%": { transform: "translateY(-10px)" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
</head>
|
|
<body class="bg-gradient-to-br from-gray-50 to-gray-100 min-h-screen">
|
|
<div class="container mx-auto max-w-5xl px-4 py-12">
|
|
<div class="relative mb-16">
|
|
<div class="absolute inset-0 -z-10 overflow-hidden">
|
|
<div
|
|
class="absolute -top-4 -left-4 w-24 h-24 bg-blue-100 rounded-full opacity-50 animate-float"></div>
|
|
<div
|
|
class="absolute top-0 right-0 w-32 h-32 bg-green-100 rounded-full opacity-50 animate-float"
|
|
style="animation-delay: 1s"></div>
|
|
<div
|
|
class="absolute bottom-0 left-1/4 w-16 h-16 bg-yellow-100 rounded-full opacity-50 animate-float"
|
|
style="animation-delay: 2s"></div>
|
|
</div>
|
|
|
|
<div class="text-center relative">
|
|
<div class="inline-block">
|
|
<h1
|
|
class="text-5xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-green-600 tracking-tight pb-1">
|
|
SWOT Agent
|
|
</h1>
|
|
<div
|
|
class="h-1 w-full bg-gradient-to-r from-blue-600 to-green-600 rounded-full mt-1"></div>
|
|
</div>
|
|
|
|
<p class="mt-6 text-gray-600 text-lg max-w-2xl mx-auto">
|
|
Analyze the Strengths, Weaknesses, Opportunities, and Threats<br />
|
|
of any business or product with your own personal AI agent.
|
|
</p>
|
|
|
|
<div class="flex flex-wrap justify-center gap-4 mt-6">
|
|
<span
|
|
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-100 text-blue-800">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke-width="1.5"
|
|
stroke="currentColor"
|
|
class="w-4 h-4 mr-1.5">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" />
|
|
</svg>
|
|
Instant Analysis
|
|
</span>
|
|
<span
|
|
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-100 text-green-800">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke-width="1.5"
|
|
stroke="currentColor"
|
|
class="w-4 h-4 mr-1.5">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09zM18.259 8.715L18 9.75l-.259-1.035a3.375 3.375 0 00-2.455-2.456L14.25 6l1.036-.259a3.375 3.375 0 002.455-2.456L18 2.25l.259 1.035a3.375 3.375 0 002.456 2.456L21.75 6l-1.035.259a3.375 3.375 0 00-2.456 2.456zM16.894 20.567L16.5 21.75l-.394-1.183a2.25 2.25 0 00-1.423-1.423L13.5 18.75l1.183-.394a2.25 2.25 0 001.423-1.423l.394-1.183.394 1.183a2.25 2.25 0 001.423 1.423l1.183.394-1.183.394a2.25 2.25 0 00-1.423 1.423z" />
|
|
</svg>
|
|
AI-Powered
|
|
</span>
|
|
<span
|
|
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-yellow-100 text-yellow-800">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke-width="1.5"
|
|
stroke="currentColor"
|
|
class="w-4 h-4 mr-1.5">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" />
|
|
</svg>
|
|
Comprehensive
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bg-white rounded-2xl shadow-lg p-6 mb-8">
|
|
<form
|
|
id="swot-form"
|
|
hx-post="/analyze"
|
|
hx-trigger="submit"
|
|
hx-target="#status"
|
|
class="flex flex-col sm:flex-row gap-3">
|
|
<div class="flex-grow">
|
|
<input
|
|
type="url"
|
|
name="url"
|
|
placeholder="https://example.com"
|
|
required
|
|
class="w-full px-4 py-3 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition duration-200 placeholder-gray-400" />
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
class="bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-6 rounded-lg transition duration-200 transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 shadow-md"
|
|
hx-on:click="
|
|
const [status, result] = ['#status', '#result'].map(id => document.querySelector(id));
|
|
status.style.display = 'block';
|
|
result.style.display = 'none';">
|
|
<span class="flex items-center justify-center gap-2">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
stroke-width="1.5"
|
|
stroke="currentColor"
|
|
class="w-5 h-5">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
|
|
</svg>
|
|
Analyze
|
|
</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="analysis-content">
|
|
<div
|
|
id="status"
|
|
hx-get="/status"
|
|
hx-trigger="load, every 1s"
|
|
hx-swap="innerHTML transition:false"
|
|
style="display: none"
|
|
class="bg-white rounded-2xl shadow-lg p-6 mb-8"></div>
|
|
<div
|
|
id="result"
|
|
hx-get="/result"
|
|
hx-trigger="load, every 1s[!this.querySelector('#result-container') || this.style.display === 'none']"
|
|
hx-swap="innerHTML"
|
|
hx-on::after-request="
|
|
if(this.innerHTML.trim().length > 0) {
|
|
const statusDiv = document.querySelector('#status');
|
|
if (statusDiv) statusDiv.style.display = 'none';
|
|
this.style.display = 'block';
|
|
}"></div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|