Skip to content

Commit

Permalink
ADDED: Blog Generator UI
Browse files Browse the repository at this point in the history
  • Loading branch information
AquibPy committed May 2, 2024
1 parent a6ea304 commit fb9fa30
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ percentage, missing keywords, and profile summary.
- **Input:** Users need to upload a resume file and provide a job description as text.
- **Output:** The endpoint provides insights in JSON format, including job description match.

### 17. ChatBot

- **Route:** `/blog_generator_ui`
- **Description:** Provides a simple web interface to interact with the Blog Generator.
- **Try ChatBot:** [Blog Generator](https://llm-pgc4.onrender.com/blog_generator_ui)

## Usage

Each endpoint accepts specific parameters as described in the respective endpoint documentation. Users can make POST requests to these endpoints with the required parameters to perform the desired tasks.
Expand Down
4 changes: 4 additions & 0 deletions api.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ async def home():
async def chat(request: Request):
return templates.TemplateResponse("index.html", {"request": request})

@app.get("/blog_generator_ui",description="Provides a simple web interface to interact with the Blog Generator")
async def chat(request: Request):
return templates.TemplateResponse("blog_generator.html", {"request": request})

@app.post("/invoice_extractor",description="This route extracts information from invoices based on provided images and prompts.")
async def gemini(image_file: UploadFile = File(...), prompt: str = Form(...)):
image = image_file.file.read()
Expand Down
318 changes: 318 additions & 0 deletions templates/blog_generator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Blog Generator</title>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/marked/2.0.2/marked.min.css">
<style>
body {
font-family: 'Montserrat', sans-serif;
background: linear-gradient(135deg, #f7d9c4, #f2e3c6);
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 50px auto;
padding: 40px;
background-color: #fff;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
border-radius: 10px;
display: flex;
flex-direction: column;
align-items: center;
animation: fadeIn 1s ease;
}
h1 {
text-align: center;
margin-bottom: 30px;
font-weight: 700;
color: #7a4d3b;
position: relative;
animation: slideInDown 1s ease;
}
h1::before {
content: "";
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 50px;
height: 3px;
background-color: #7a4d3b;
}
form {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30px;
animation: slideInLeft 1s ease;
}
label {
font-size: 1.2rem;
margin-bottom: 10px;
color: #7a4d3b;
}
input[type="text"] {
width: 300px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
transition: border-color 0.3s ease;
animation: fadeIn 1s ease;
}
input[type="text"]:focus {
border-color: #7a4d3b;
outline: none;
}
button {
padding: 10px 20px;
background-color: #7a4d3b;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
display: flex;
justify-content: center;
align-items: center;
animation: slideInRight 1s ease;
}
button:hover {
background-color: #6b4335;
}
button i {
margin-right: 10px;
}
#output {
border: 1px solid #ccc;
padding: 20px;
border-radius: 5px;
background-color: #f7f7f7;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
animation: fadeIn 1s ease;
}
#output:hover {
transform: scale(1.02);
}
#output h2 {
margin-top: 0;
color: #7a4d3b;
position: relative;
padding-bottom: 10px;
}
#output h2::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 50px;
height: 2px;
background-color: #7a4d3b;
}
#output p {
margin-bottom: 10px;
color: #555;
}
.loading {
display: none;
justify-content: center;
align-items: center;
height: 100px;
}
.spinner {
border: 4px solid rgba(122, 77, 59, 0.2);
border-left-color: #7a4d3b;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.btn-container {
display: flex;
justify-content: center;
margin-top: 20px;
animation: fadeIn 1s ease;
}
.btn-container button {
margin: 0 10px;
}
.copy-btn {
background-color: #6c757d;
transition: background-color 0.3s ease;
}
.copy-btn:hover {
background-color: #5a6268;
}
@media (max-width: 600px) {
.container {
padding: 20px;
max-width: 100%;
}
input[type="text"] {
width: 100%;
max-width: 100%;
}
}
@media (max-width: 400px) {
h1 {
font-size: 24px;
}
label {
font-size: 1rem;
}
input[type="text"] {
width: 250px;
}
}
@media (max-width: 320px) {
h1 {
font-size: 20px;
}
input[type="text"] {
width: 200px;
}
}
@media (max-width: 280px) {
h1 {
font-size: 18px;
}
input[type="text"] {
width: 160px;
}
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes slideInDown {
0% {
transform: translateY(-100%);
}
100% {
transform: translateY(0);
}
}
@keyframes slideInLeft {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0);
}
}
@keyframes slideInRight {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(0);
}
}
</style>
</head>
<body>
<div class="container">
<h1>Blog Generator</h1>
<form id="blogForm">
<label for="topic">Topic:</label>
<input type="text" id="topic" name="topic" placeholder="Enter a topic">
<button type="submit"><i class="fas fa-pen"></i>Generate Blog</button>
</form>
<div class="loading" id="loadingSpinner">
<div class="spinner"></div>
</div>
<div id="output"></div>
<div id="notification"></div>
<div class="btn-container" id="btnContainer" style="display: none;">
<button class="copy-btn" onclick="copyToClipboard()"><i class="far fa-copy"></i> Copy to Clipboard</button>
</div>
<div class="follow-container">
<p>Follow me on <a href='https://github.com/AquibPy' target='_blank'> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
</svg></a></p>
</div>
<footer>
<p>© Made with ❤️ by <a href='https://www.linkedin.com/in/aquibpy/' target='_blank'>Mohd Aquib</a></p>
</footer>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/2.0.2/marked.min.js"></script>
<script>
const blogForm = document.getElementById('blogForm');
const loadingSpinner = document.getElementById('loadingSpinner');
const output = document.getElementById('output');
const btnContainer = document.getElementById('btnContainer');
const notificationContainer = document.getElementById('notification');

blogForm.addEventListener('submit', async function(event) {
event.preventDefault();

const topic = document.getElementById('topic').value;

loadingSpinner.style.display = 'flex';
btnContainer.style.display = 'none';

const response = await fetch('https://llm-pgc4.onrender.com/blog_generator', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
'topic': topic,
}),
});

loadingSpinner.style.display = 'none';

const data = await response.json();

if (data && data.response) {
const htmlOutput = marked(data.response);
output.innerHTML = `<h2>Generated Blog:</h2>${htmlOutput}`;
btnContainer.style.display = 'flex';
showNotification('Blog generated successfully!');
} else {
output.innerHTML = '<p>No blog generated. Please try again.</p>';
btnContainer.style.display = 'none';
showNotification('Failed to generate blog. Please try again.');
}
});

function copyToClipboard() {
const blogContent = output.innerHTML;
navigator.clipboard.writeText(blogContent)
.then(() => {
showNotification('Copied!');
})
.catch((error) => {
console.error('Failed to copy blog content: ', error);
});
}

function showNotification(message) {
const notification = document.createElement('div');
notification.classList.add('notification');
notification.textContent = message;
notificationContainer.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 2000);
}
</script>
</body>
</html>

0 comments on commit fb9fa30

Please sign in to comment.