eienmojiki's picture
Upload 21 files
fbcf5d4 verified
let isDarkMode = false;
let fontData = [];
// Load available fonts when page loads
async function loadAvailableFonts() {
try {
const response = await fetch("/api/fonts");
fontData = await response.json();
// Populate both quote and author font family selects
const quoteFontFamily = document.getElementById("quoteFontFamily");
const authorFontFamily = document.getElementById("authorFontFamily");
const fontOptions = fontData
.map((font) => `<option value="${font.family}">${font.family}</option>`)
.join("");
quoteFontFamily.innerHTML = fontOptions;
authorFontFamily.innerHTML = fontOptions;
// Initialize variations for both
if (fontData.length > 0) {
updateFontVariations("quote", fontData[0].family);
updateFontVariations("author", fontData[0].family);
generateQuote();
}
} catch (error) {
console.error("Error loading fonts:", error);
showStatus("Error loading fonts", "error");
}
}
// Update font variations based on selected font family
function updateFontVariations(type, family) {
const font = fontData.find((f) => f.family === family);
if (!font) return;
const styleSelect = document.getElementById(`${type}FontStyle`);
// Get unique styles
const styles = new Set(font.variations.map((v) => v.style));
// Update style options
styleSelect.innerHTML = Array.from(styles)
.map(
(style) => `<option value="${style}">${formatFontStyle(style)}</option>`
)
.join("");
}
// Format font weight for display
function formatFontWeight(weight) {
switch (weight) {
case "normal":
return "Regular";
case "bold":
return "Bold";
case "light":
return "Light";
case "medium":
return "Medium";
default:
return weight.charAt(0).toUpperCase() + weight.slice(1);
}
}
// Format font style for display
function formatFontStyle(style) {
switch (style) {
case "normal":
return "Normal";
case "italic":
return "Italic";
default:
return style.charAt(0).toUpperCase() + style.slice(1);
}
}
// Setup color pickers with hex input sync
function setupColorPickers() {
const colorInputs = document.querySelectorAll('input[type="color"]');
colorInputs.forEach((input) => {
const textInput = document.getElementById(input.id + "Text");
// Update text input when color changes
input.addEventListener("input", () => {
textInput.value = input.value.toUpperCase();
});
// Update color input when valid hex is entered
textInput.addEventListener("input", () => {
let hex = textInput.value.trim();
if (!hex.startsWith("#")) {
hex = "#" + hex;
}
if (/^#[0-9A-F]{6}$/i.test(hex)) {
input.value = hex;
}
});
// Format hex on blur
textInput.addEventListener("blur", () => {
let hex = textInput.value.trim();
if (!hex.startsWith("#")) {
hex = "#" + hex;
}
if (/^#[0-9A-F]{6}$/i.test(hex)) {
textInput.value = hex.toUpperCase();
input.value = hex;
} else {
textInput.value = input.value.toUpperCase();
}
});
});
}
async function generateQuote() {
const generateBtn = document.querySelector(".btn-primary");
const btnText = generateBtn.querySelector(".btn-text");
const btnLoader = generateBtn.querySelector(".btn-loader");
try {
// Show loading state
generateBtn.disabled = true;
btnText.style.opacity = "0";
btnLoader.style.display = "block";
document.getElementById("loading").style.display = "flex";
document.getElementById("quoteImage").style.opacity = "0.5";
const data = {
text: document.getElementById("quoteText").value,
author: document.getElementById("author").value,
bgColor: document.getElementById("bgColor").value,
barColor: document.getElementById("barColor").value,
textColor: document.getElementById("textColor").value,
authorColor: document.getElementById("authorColor").value,
quoteFontFamily: document.getElementById("quoteFontFamily").value,
quoteFontWeight: "bold", // Force bold for quote
quoteFontStyle: document.getElementById("quoteFontStyle").value,
authorFontFamily: document.getElementById("authorFontFamily").value,
authorFontWeight: "normal", // Force normal for author
authorFontStyle: document.getElementById("authorFontStyle").value,
barWidth: parseInt(document.getElementById("barWidth").value),
};
const response = await fetch("/api/generate-quote", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
const result = await response.json();
if (result.success) {
const img = document.getElementById("quoteImage");
img.src = result.imageUrl;
img.style.opacity = "1";
showStatus("Quote generated successfully!", "success");
} else {
throw new Error(result.error);
}
} catch (error) {
showStatus(error.message || "Error generating quote", "error");
console.error(error);
} finally {
// Reset loading state
generateBtn.disabled = false;
btnText.style.opacity = "1";
btnLoader.style.display = "none";
document.getElementById("loading").style.display = "none";
}
}
function downloadQuote() {
const img = document.getElementById("quoteImage");
if (!img.src || img.src === window.location.href) {
showStatus("Generate a quote first!", "error");
return;
}
const link = document.createElement("a");
const timestamp = new Date().toISOString().split("T")[0];
link.download = `quote-${timestamp}.png`;
link.href = img.src;
link.click();
}
async function viewRequests() {
try {
const response = await fetch("/api/requests-history");
const requests = await response.json();
const requestsList = document.getElementById("requestsList");
requestsList.innerHTML = requests
.map(
(req) => `
<div class="request-item">
<div class="request-time">${new Date(
req.timestamp
).toLocaleString()}</div>
<pre class="request-data">${JSON.stringify(
req.request,
null,
2
)}</pre>
</div>
`
)
.join("");
document.getElementById("requestsModal").style.display = "block";
} catch (error) {
showStatus("Error fetching requests", "error");
console.error(error);
}
}
function closeModal() {
document.getElementById("requestsModal").style.display = "none";
}
function toggleTheme() {
isDarkMode = !isDarkMode;
document.documentElement.setAttribute(
"data-theme",
isDarkMode ? "dark" : "light"
);
document.querySelector(".theme-toggle").textContent = isDarkMode
? "☀️"
: "🌙";
}
function showStatus(message, type) {
const status = document.getElementById("status");
status.textContent = message;
status.style.color = type === "success" ? "var(--success)" : "#ef4444";
status.style.display = "block";
setTimeout(() => {
status.style.display = "none";
}, 3000);
}
// Event Listeners
document.addEventListener("DOMContentLoaded", () => {
loadAvailableFonts();
setupColorPickers();
// Font family change listeners
document.getElementById("quoteFontFamily").addEventListener("change", (e) => {
updateFontVariations("quote", e.target.value);
});
document
.getElementById("authorFontFamily")
.addEventListener("change", (e) => {
updateFontVariations("author", e.target.value);
});
// Check system theme preference
if (
window.matchMedia &&
window.matchMedia("(prefers-color-scheme: dark)").matches
) {
toggleTheme();
}
// Setup bar width value display
const barWidthSlider = document.getElementById("barWidth");
const barWidthValue = document.getElementById("barWidthValue");
barWidthSlider.addEventListener("input", () => {
barWidthValue.textContent = `${barWidthSlider.value}px`;
});
});
// Close modal when clicking outside
window.onclick = function (event) {
const modal = document.getElementById("requestsModal");
if (event.target === modal) {
closeModal();
}
};