|
|
<!DOCTYPE html>
|
|
|
<html lang="en">
|
|
|
<head>
|
|
|
<meta charset="UTF-8" />
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
|
<title>Thirukkural Wisdom</title>
|
|
|
<link
|
|
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Noto+Sans+Tamil:wght@400;500;600&display=swap"
|
|
|
rel="stylesheet"
|
|
|
/>
|
|
|
<style>
|
|
|
* {
|
|
|
margin: 0;
|
|
|
padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
body {
|
|
|
font-family: "Poppins", sans-serif;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
min-height: 100vh;
|
|
|
color: #333;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
max-width: 900px;
|
|
|
margin: 0 auto;
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
|
|
|
.header {
|
|
|
text-align: center;
|
|
|
margin-bottom: 40px;
|
|
|
padding: 30px 0;
|
|
|
}
|
|
|
|
|
|
.header h1 {
|
|
|
color: white;
|
|
|
font-size: 2.5rem;
|
|
|
font-weight: 600;
|
|
|
margin-bottom: 10px;
|
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.header p {
|
|
|
color: rgba(255, 255, 255, 0.9);
|
|
|
font-size: 1.1rem;
|
|
|
font-weight: 300;
|
|
|
}
|
|
|
|
|
|
|
|
|
.search-section {
|
|
|
background: white;
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
|
|
margin-bottom: 30px;
|
|
|
}
|
|
|
|
|
|
.search-form {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 20px;
|
|
|
}
|
|
|
|
|
|
.input-group {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
gap: 8px;
|
|
|
}
|
|
|
|
|
|
.input-group label {
|
|
|
font-weight: 500;
|
|
|
color: #555;
|
|
|
font-size: 0.95rem;
|
|
|
}
|
|
|
|
|
|
.query-input {
|
|
|
padding: 15px 20px;
|
|
|
border: 2px solid #e0e6ff;
|
|
|
border-radius: 12px;
|
|
|
font-size: 1rem;
|
|
|
transition: all 0.3s ease;
|
|
|
font-family: "Poppins", sans-serif;
|
|
|
background: #fafbff;
|
|
|
}
|
|
|
|
|
|
.query-input:focus {
|
|
|
outline: none;
|
|
|
border-color: #667eea;
|
|
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
|
background: white;
|
|
|
}
|
|
|
|
|
|
.form-row {
|
|
|
display: flex;
|
|
|
gap: 20px;
|
|
|
align-items: end;
|
|
|
}
|
|
|
|
|
|
.language-selector {
|
|
|
flex: 1;
|
|
|
}
|
|
|
|
|
|
.language-selector select {
|
|
|
padding: 12px 15px;
|
|
|
border: 2px solid #e0e6ff;
|
|
|
border-radius: 12px;
|
|
|
font-size: 1rem;
|
|
|
font-family: "Poppins", sans-serif;
|
|
|
background: #fafbff;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.language-selector select:focus {
|
|
|
outline: none;
|
|
|
border-color: #667eea;
|
|
|
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
|
|
background: white;
|
|
|
}
|
|
|
|
|
|
.search-button {
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: white;
|
|
|
border: none;
|
|
|
padding: 15px 30px;
|
|
|
border-radius: 12px;
|
|
|
font-size: 1.1rem;
|
|
|
font-weight: 600;
|
|
|
cursor: pointer;
|
|
|
transition: all 0.3s ease;
|
|
|
font-family: "Poppins", sans-serif;
|
|
|
min-width: 180px;
|
|
|
}
|
|
|
|
|
|
.search-button:hover {
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
|
|
|
}
|
|
|
|
|
|
.search-button:active {
|
|
|
transform: translateY(0);
|
|
|
}
|
|
|
|
|
|
.search-button:disabled {
|
|
|
opacity: 0.6;
|
|
|
cursor: not-allowed;
|
|
|
transform: none;
|
|
|
}
|
|
|
|
|
|
|
|
|
.loading {
|
|
|
text-align: center;
|
|
|
padding: 40px;
|
|
|
color: #667eea;
|
|
|
}
|
|
|
|
|
|
.loading-spinner {
|
|
|
width: 40px;
|
|
|
height: 40px;
|
|
|
border: 4px solid #e0e6ff;
|
|
|
border-top: 4px solid #667eea;
|
|
|
border-radius: 50%;
|
|
|
animation: spin 1s linear infinite;
|
|
|
margin: 0 auto 15px;
|
|
|
}
|
|
|
|
|
|
@keyframes spin {
|
|
|
0% {
|
|
|
transform: rotate(0deg);
|
|
|
}
|
|
|
100% {
|
|
|
transform: rotate(360deg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
.results-section {
|
|
|
display: none;
|
|
|
}
|
|
|
|
|
|
.results-section.show {
|
|
|
display: block;
|
|
|
}
|
|
|
|
|
|
|
|
|
.explanation-card {
|
|
|
background: white;
|
|
|
border-radius: 20px;
|
|
|
padding: 30px;
|
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
|
|
margin-bottom: 30px;
|
|
|
border-left: 5px solid #667eea;
|
|
|
}
|
|
|
|
|
|
.explanation-card h3 {
|
|
|
color: #333;
|
|
|
font-size: 1.3rem;
|
|
|
margin-bottom: 20px;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 10px;
|
|
|
}
|
|
|
|
|
|
.explanation-text {
|
|
|
color: #555;
|
|
|
font-size: 1rem;
|
|
|
line-height: 1.7;
|
|
|
}
|
|
|
|
|
|
.explanation-text p {
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.explanation-text strong {
|
|
|
color: #333;
|
|
|
}
|
|
|
|
|
|
.explanation-text ul,
|
|
|
.explanation-text ol {
|
|
|
padding-left: 20px;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.explanation-text li {
|
|
|
margin-bottom: 5px;
|
|
|
}
|
|
|
|
|
|
|
|
|
.kurals-container {
|
|
|
display: grid;
|
|
|
gap: 20px;
|
|
|
}
|
|
|
|
|
|
.kural-card {
|
|
|
background: white;
|
|
|
border-radius: 15px;
|
|
|
padding: 25px;
|
|
|
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.08);
|
|
|
transition: all 0.3s ease;
|
|
|
border: 1px solid #f0f0f0;
|
|
|
}
|
|
|
|
|
|
.kural-card:hover {
|
|
|
transform: translateY(-3px);
|
|
|
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.12);
|
|
|
}
|
|
|
|
|
|
.kural-number {
|
|
|
display: inline-block;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: white;
|
|
|
padding: 5px 12px;
|
|
|
border-radius: 20px;
|
|
|
font-size: 0.85rem;
|
|
|
font-weight: 600;
|
|
|
margin-bottom: 15px;
|
|
|
}
|
|
|
|
|
|
.kural-tamil {
|
|
|
font-family: "Noto Sans Tamil", sans-serif;
|
|
|
font-size: 1.2rem;
|
|
|
line-height: 1.8;
|
|
|
color: #2c3e50;
|
|
|
margin-bottom: 15px;
|
|
|
font-weight: 500;
|
|
|
text-align: center;
|
|
|
background: #f8f9ff;
|
|
|
padding: 15px;
|
|
|
border-radius: 10px;
|
|
|
white-space: pre-line;
|
|
|
}
|
|
|
|
|
|
.kural-english {
|
|
|
font-size: 1rem;
|
|
|
color: #555;
|
|
|
font-style: italic;
|
|
|
text-align: center;
|
|
|
margin-bottom: 15px;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
.kural-category {
|
|
|
display: inline-block;
|
|
|
background: #e8f2ff;
|
|
|
color: #667eea;
|
|
|
padding: 4px 10px;
|
|
|
border-radius: 15px;
|
|
|
font-size: 0.8rem;
|
|
|
font-weight: 500;
|
|
|
}
|
|
|
|
|
|
.kural-explanation {
|
|
|
margin-top: 15px;
|
|
|
padding-top: 15px;
|
|
|
border-top: 1px solid #f0f0f0;
|
|
|
color: #666;
|
|
|
font-size: 0.9rem;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
|
|
|
.error-message {
|
|
|
background: #fff5f5;
|
|
|
border: 1px solid #fed7d7;
|
|
|
border-radius: 12px;
|
|
|
padding: 20px;
|
|
|
color: #c53030;
|
|
|
text-align: center;
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
.container {
|
|
|
padding: 15px;
|
|
|
}
|
|
|
|
|
|
.header h1 {
|
|
|
font-size: 2rem;
|
|
|
}
|
|
|
|
|
|
.search-section {
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.form-row {
|
|
|
flex-direction: column;
|
|
|
gap: 15px;
|
|
|
}
|
|
|
|
|
|
.search-button {
|
|
|
width: 100%;
|
|
|
}
|
|
|
|
|
|
.explanation-card,
|
|
|
.kural-card {
|
|
|
padding: 20px;
|
|
|
}
|
|
|
|
|
|
.kural-tamil {
|
|
|
font-size: 1.1rem;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
display: none;
|
|
|
gap: 10px;
|
|
|
margin-top: 15px;
|
|
|
}
|
|
|
|
|
|
.action-btn {
|
|
|
padding: 8px 15px;
|
|
|
border: 1px solid #ddd;
|
|
|
border-radius: 8px;
|
|
|
background: white;
|
|
|
cursor: pointer;
|
|
|
font-size: 0.85rem;
|
|
|
transition: all 0.3s ease;
|
|
|
}
|
|
|
|
|
|
.action-btn:hover {
|
|
|
background: #f5f5f5;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div class="container">
|
|
|
|
|
|
<div class="header">
|
|
|
<h1>திருக்குறள் Wisdom</h1>
|
|
|
<p>Discover timeless guidance from Thiruvalluvar's sacred verses</p>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div class="search-section">
|
|
|
<form class="search-form" id="searchForm">
|
|
|
<div class="input-group">
|
|
|
<label for="query">What guidance are you seeking?</label>
|
|
|
<textarea
|
|
|
id="query"
|
|
|
class="query-input"
|
|
|
placeholder="e.g., I want to be happy in my life, How to be a good leader, What is true friendship..."
|
|
|
rows="3"
|
|
|
required
|
|
|
></textarea>
|
|
|
</div>
|
|
|
|
|
|
<div class="form-row">
|
|
|
<div class="language-selector">
|
|
|
<label for="language">Language Preference</label>
|
|
|
<select id="language" name="language">
|
|
|
<option value="en">English</option>
|
|
|
<option value="ta">தமிழ்</option>
|
|
|
</select>
|
|
|
</div>
|
|
|
<button type="submit" class="search-button">✨ Find Wisdom</button>
|
|
|
</div>
|
|
|
</form>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div id="loading" class="loading" style="display: none">
|
|
|
<div class="loading-spinner"></div>
|
|
|
<p>Searching ancient wisdom...</p>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div id="errorMessage" class="error-message" style="display: none"></div>
|
|
|
|
|
|
|
|
|
<div id="resultsSection" class="results-section">
|
|
|
|
|
|
<div id="explanationCard" class="explanation-card">
|
|
|
<h3>🧘 Answer to Reflect On</h3>
|
|
|
<div id="explanationText" class="explanation-text"></div>
|
|
|
</div>
|
|
|
|
|
|
|
|
|
<div id="kuralsContainer" class="kurals-container"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
const searchForm = document.getElementById("searchForm");
|
|
|
const queryInput = document.getElementById("query");
|
|
|
const languageSelect = document.getElementById("language");
|
|
|
const searchButton = document.querySelector(".search-button");
|
|
|
const loading = document.getElementById("loading");
|
|
|
const errorMessage = document.getElementById("errorMessage");
|
|
|
const resultsSection = document.getElementById("resultsSection");
|
|
|
const explanationText = document.getElementById("explanationText");
|
|
|
const kuralsContainer = document.getElementById("kuralsContainer");
|
|
|
|
|
|
|
|
|
const API_BASE_URL =
|
|
|
"https://viswadarshan06-Thirukkural-AI-Backend.hf.space";
|
|
|
|
|
|
|
|
|
searchForm.addEventListener("submit", async (e) => {
|
|
|
e.preventDefault();
|
|
|
|
|
|
const query = queryInput.value.trim();
|
|
|
if (!query) return;
|
|
|
|
|
|
|
|
|
showLoading();
|
|
|
hideError();
|
|
|
hideResults();
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetch(`${API_BASE_URL}/search/`, {
|
|
|
method: "POST",
|
|
|
headers: {
|
|
|
"Content-Type": "application/json",
|
|
|
},
|
|
|
body: JSON.stringify({
|
|
|
query: query,
|
|
|
lang: languageSelect.value,
|
|
|
top_k: 3,
|
|
|
}),
|
|
|
});
|
|
|
|
|
|
if (!response.ok) {
|
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
|
}
|
|
|
|
|
|
const data = await response.json();
|
|
|
displayResults(data);
|
|
|
} catch (error) {
|
|
|
console.error("Search error:", error);
|
|
|
showError(
|
|
|
"Unable to search for wisdom at this time. Please try again later."
|
|
|
);
|
|
|
} finally {
|
|
|
hideLoading();
|
|
|
}
|
|
|
});
|
|
|
|
|
|
function showLoading() {
|
|
|
loading.style.display = "block";
|
|
|
searchButton.disabled = true;
|
|
|
}
|
|
|
|
|
|
function hideLoading() {
|
|
|
loading.style.display = "none";
|
|
|
searchButton.disabled = false;
|
|
|
}
|
|
|
|
|
|
function showError(message) {
|
|
|
errorMessage.textContent = message;
|
|
|
errorMessage.style.display = "block";
|
|
|
}
|
|
|
|
|
|
function hideError() {
|
|
|
errorMessage.style.display = "none";
|
|
|
}
|
|
|
|
|
|
function hideResults() {
|
|
|
resultsSection.classList.remove("show");
|
|
|
}
|
|
|
|
|
|
function showResults() {
|
|
|
resultsSection.classList.add("show");
|
|
|
}
|
|
|
|
|
|
function displayResults(data) {
|
|
|
|
|
|
explanationText.innerHTML = formatMarkdown(data.explanation);
|
|
|
|
|
|
|
|
|
kuralsContainer.innerHTML = "";
|
|
|
data.matched_kurals.forEach((kural) => {
|
|
|
const kuralCard = createKuralCard(kural);
|
|
|
kuralsContainer.appendChild(kuralCard);
|
|
|
});
|
|
|
|
|
|
showResults();
|
|
|
}
|
|
|
|
|
|
function createKuralCard(kural) {
|
|
|
const card = document.createElement("div");
|
|
|
card.className = "kural-card";
|
|
|
|
|
|
|
|
|
const tamilText = kural.Tamil
|
|
|
? kural.Tamil.replace(/\n/g, "\n")
|
|
|
: "Tamil text not available";
|
|
|
|
|
|
card.innerHTML = `
|
|
|
<div class="kural-number">Kural ${kural.Number}</div>
|
|
|
<div class="kural-tamil">${tamilText}</div>
|
|
|
<div class="kural-english">${
|
|
|
kural.English || "English translation not available"
|
|
|
}</div>
|
|
|
<div class="kural-category">${kural.Category || "General"}</div>
|
|
|
${
|
|
|
kural.Explanation
|
|
|
? `<div class="kural-explanation">${kural.Explanation}</div>`
|
|
|
: ""
|
|
|
}
|
|
|
|
|
|
<!-- Hidden action buttons for future features -->
|
|
|
<div class="action-buttons">
|
|
|
<button class="action-btn">📋 Copy</button>
|
|
|
<button class="action-btn">🔊 Speak</button>
|
|
|
<button class="action-btn">💾 Save</button>
|
|
|
</div>
|
|
|
`;
|
|
|
|
|
|
return card;
|
|
|
}
|
|
|
|
|
|
function formatMarkdown(text) {
|
|
|
if (!text) return "";
|
|
|
|
|
|
|
|
|
return text
|
|
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
|
.replace(/^- (.+)$/gm, "<li>$1</li>")
|
|
|
.replace(/(<li>.*<\/li>)/s, "<ul>$1</ul>")
|
|
|
.replace(/^\d+\. (.+)$/gm, "<li>$1</li>")
|
|
|
.replace(/(<li>.*<\/li>)/s, "<ol>$1</ol>")
|
|
|
.replace(/\n\n/g, "</p><p>")
|
|
|
.replace(/^(.+)$/, "<p>$1</p>")
|
|
|
.replace(/<p><\/p>/g, "");
|
|
|
}
|
|
|
|
|
|
|
|
|
queryInput.addEventListener("input", function () {
|
|
|
this.style.height = "auto";
|
|
|
this.style.height = this.scrollHeight + "px";
|
|
|
});
|
|
|
</script>
|
|
|
</body>
|
|
|
</html>
|
|
|
|