<div class="position-absolute top-0 end-0 mt-2 me-3">
<button
id="api"
type="button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#myModal"
>
Add API Key
</button>
</div>
<div class="container mt-5">
<div class="message alert alert-danger text-center" role="alert"></div>
<div
class="modal fade"
id="myModal"
tabindex="-1"
aria-labelledby="exampleModalLabel"
aria-hidden="true"
>
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">
Your API Key remains stored locally in your browser
</h5>
</div>
<div class="modal-body">
<div class="form-group">
<label for="apikey">API KEY</label>
<input type="text" class="form-control" id="apikey" />
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
<button type="button" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
<h1 class="header text-center display-2 fw-bold">AI Quote Generator</h1>
<!-- Main -->
<div class="d-md-flex h-md-100 my-5 align-items-center">
<div class="col-md-6 p-0 h-md-100">
<div class="d-md-flex align-items-center h-100 p-5 text-center justify-content-center category-wrapper">
<div class="pt-5 pb-5">
<p class="fs-5">
Create the perfect quote based on your current mood..
</p>
<input
id="input"
name="mood"
type="text"
placeholder="Enter your current mood"
class="form-control mb-4 mx-auto w-75 text-center"
style="width: 60%; display: inline-block"
/>
</div>
</div>
</div>
<div class="col-md-6 p-0 h-md-100">
<div class="d-md-flex align-items-center h-md-100 p-5 text-center justify-content-center vstack">
<p class="fs-5">
..or choose from our custom categories
</p>
<div class="quotes justify-content-center">
</div>
</div>
</div>
</div>
<!-- End Main -->
<div class="quotes-container text-center mt-4">
<button
id="generate"
class="generate-btn btn btn-primary"
type="submit"
>
Generate Quotes
</button>
<div class="d-flex justify-content-center mt-3">
<div id="loader" class="spinner-border" role="status">
</div>
</div>
</div>
</div>
</div>
<div class="container text-center mt-5 mb-4">
<div id="result" class="row">
<!-- <div class="col-lg-6 mt-5 mb-4">
<div class="card">
<div class="card-body">
<p class="card-text">
With supporting text below text below as a naturaltext below as
a natural as a natural text below as a natural lead-in to
additional content.
</p>
</div>
</div>
</div>
<div class="col-md-6 mt-5 mb-4">
<div class="card">
<div class="card-body">
<p class="card-text">
With supporting text below as a natural lead-in to additional
content.
</p>
</div>
</div>
</div> -->
</div>
</div>
@import url("https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap");
body {
font-family: "DM Mono", monospace;
}
.form-group {
margin: 2rem 0;
}
label {
margin-bottom: 1rem;
}
@media (min-width: 768px) {
.category-wrapper {
border-right: 2px solid #999;
}
}
#loader,
.message,
.radio-group input[type="radio"]{
display: none;
}
$("#myModal").on("shown.bs.modal", function () {
const saveButton = document.querySelector("#myModal .btn-primary");
const apiKeyInput = document.querySelector("#apikey");
saveButton.addEventListener("click", function () {
const apiKeyValue = apiKeyInput.value;
localStorage.setItem("API_KEY", apiKeyValue);
$("#myModal").modal("hide");
});
});
function displayError(valueText,messageText) {
const message = document.querySelector(".message");
if (valueText === "") {
message.textContent = messageText;
message.style.display = "block";
}
setTimeout(() => {
message.textContent = "";
message.style.display = "none";
}, 4000);
return;
}
const loader = document.getElementById("loader");
const getData = async (prompt, API_KEY) => {
try {
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: `Generate 10 quotes about ${prompt}`,
},
],
temperature: 0.7,
}),
});
const data = await response.json();
loader.style.display = "none";
return data;
} catch (error) {
loader.style.display = "none";
return data;
}
};
const categories = [
"motivation",
"life",
"hope",
"funny",
"love",
"philosophy",
"sadness",
];
const quotes = document.querySelector(".quotes");
const mappedCategories = categories.map((category) => {
capitalizeText = category.charAt(0).toUpperCase() + category.slice(1);
return `
<input
type="radio"
class="btn-check"
name="mood"
id="${category}"
value="${category}"
autocomplete="off"
/>
<label
class="btn btn-secondary align-items-center justify-content-center"
for="${category}"
>${capitalizeText}</label>
`;
});
quotes.innerHTML = mappedCategories.join("");
const generateBtn = document.querySelector(".generate-btn");
generateBtn.addEventListener("click", async (e) => {
e.preventDefault();
const key = localStorage.getItem("API_KEY");
if (!key) {
displayError("","Please add your OPENAI API Key, The KEY will be stored locally on your browser");
return;
}
let prompt = "";
let radio = document.querySelector('input[name="mood"]:checked');
if (document.querySelector('input[name="mood"]:checked')) {
radio = document.querySelector('input[name="mood"]:checked');
prompt = radio.value;
} else {
CustomInput = document.getElementById("input");
prompt = CustomInput.value;
}
if (!prompt) {
displayError(prompt,'Please choose a category or provide a custom mood"');
return;
}
loader.style.display = "block";
const data = await getData(prompt, key);
if (data.choices) {
const container = document.getElementById("result");
// data from aync
const quotesArray = data.choices[0].message.content.split("\n");
const mappedArray = quotesArray.map((quote) => {
const trimmedQuote = quote.replace(/^\d+\.|"$/g, "").trim();
return ` <div class="col-sm-6 mt-5 mb-4">
<div class="card">
<div class="card-body">
<p class="card-text">${trimmedQuote}</p></div>
</div>
</div>
`;
});
container.innerHTML = mappedArray.join("");
} else {
displayError("",data.error.message )
}
CustomInput.value = "";
});
const inputField = document.getElementById("input");
inputField.addEventListener("input", (e) => {
e.preventDefault();
const radio = document.querySelector('input[name="mood"]:checked');
if (radio) {
radio.checked = false;
}
});
This Pen doesn't use any external JavaScript resources.