mirror of
https://github.com/Rainyy21/Front-end-Design-Project.git
synced 2026-10-10 22:50:23 -04:00
modify it so it running
This commit is contained in:
@@ -0,0 +1,72 @@
|
|||||||
|
import sqlite3, os
|
||||||
|
from flask import Flask, render_template, request, redirect, url_for
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
DB_NAME = './db/my_library.db'
|
||||||
|
UPLOAD_FOLDER = 'static/covers'
|
||||||
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||||
|
|
||||||
|
def init_db():
|
||||||
|
conn = sqlite3.connect(DB_NAME)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.executescript('''
|
||||||
|
CREATE TABLE IF NOT EXISTS media (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
title TEXT NOT NULL, type TEXT, release_year INTEGER, image_path TEXT DEFAULT 'default.jpg'
|
||||||
|
);
|
||||||
|
CREATE TABLE IF NOT EXISTS books (book_id INTEGER PRIMARY KEY, author TEXT, FOREIGN KEY (book_id) REFERENCES media (id));
|
||||||
|
CREATE TABLE IF NOT EXISTS shows (show_id INTEGER PRIMARY KEY, network TEXT, FOREIGN KEY (show_id) REFERENCES media (id));
|
||||||
|
CREATE TABLE IF NOT EXISTS genres (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE);
|
||||||
|
CREATE TABLE IF NOT EXISTS media_genres (media_id INTEGER, genre_id INTEGER);
|
||||||
|
''')
|
||||||
|
genres = [('Sci-Fi',), ('Fantasy',), ('Horror',), ('Drama',), ('Comedy',)]
|
||||||
|
cursor.executemany("INSERT OR IGNORE INTO genres (name) VALUES (?)", genres)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
conn = sqlite3.connect(DB_NAME)
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
|
query = """
|
||||||
|
SELECT m.*, b.author, s.network, GROUP_CONCAT(g.name, ', ') as genre_list
|
||||||
|
FROM media m
|
||||||
|
LEFT JOIN books b ON m.id = b.book_id
|
||||||
|
LEFT JOIN shows s ON m.id = s.show_id
|
||||||
|
LEFT JOIN media_genres mg ON m.id = mg.media_id
|
||||||
|
LEFT JOIN genres g ON mg.genre_id = g.id
|
||||||
|
GROUP BY m.id
|
||||||
|
"""
|
||||||
|
items = conn.execute(query).fetchall()
|
||||||
|
all_genres = conn.execute("SELECT * FROM genres").fetchall()
|
||||||
|
conn.close()
|
||||||
|
return render_template('main.html', items=items, genres=all_genres)
|
||||||
|
|
||||||
|
@app.route('/add', methods=['POST'])
|
||||||
|
def add_media():
|
||||||
|
title, m_type, year = request.form['title'], request.form['type'], request.form['year']
|
||||||
|
extra, genre_id = request.form['extra_info'], request.form['genre_id']
|
||||||
|
|
||||||
|
file = request.files.get('cover_image')
|
||||||
|
filename = file.filename if file and file.filename != '' else 'default.jpg'
|
||||||
|
if file and file.filename != '':
|
||||||
|
file.save(os.path.join(UPLOAD_FOLDER, filename))
|
||||||
|
|
||||||
|
conn = sqlite3.connect(DB_NAME)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute("INSERT INTO media (title, type, release_year, image_path) VALUES (?, ?, ?, ?)", (title, m_type, year, filename))
|
||||||
|
m_id = cursor.lastrowid
|
||||||
|
cursor.execute("INSERT INTO media_genres (media_id, genre_id) VALUES (?, ?)", (m_id, genre_id))
|
||||||
|
|
||||||
|
if m_type == 'Book':
|
||||||
|
cursor.execute("INSERT INTO books (book_id, author) VALUES (?, ?)", (m_id, extra))
|
||||||
|
else:
|
||||||
|
cursor.execute("INSERT INTO shows (show_id, network) VALUES (?, ?)", (m_id, extra))
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return redirect(url_for('index'))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
init_db()
|
||||||
|
app.run(debug=True)
|
||||||
Binary file not shown.
@@ -1,76 +0,0 @@
|
|||||||
import sqlite3
|
|
||||||
|
|
||||||
def init_db():
|
|
||||||
conn = sqlite3.connect('my_library.db')
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.executescript('''
|
|
||||||
CREATE A TABLE IF NOT EXISTS media(
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
title TEXT NOT NULL,
|
|
||||||
type TEXT CHECK(type IN ('Book', 'Show')),
|
|
||||||
release_year INTEGER
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE A TABLE IF NOT EXISTS books(
|
|
||||||
book_id INTEGER PRIMARY KEY,
|
|
||||||
author TEXT,
|
|
||||||
page INTEGER,
|
|
||||||
FOREIGN KEY (book_id) REFERENCES media (id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE A TABLE IF NOT EXISTS shows(
|
|
||||||
show_id INTEGER PRIMARY KEY,
|
|
||||||
network TEXT,
|
|
||||||
episodes INTEGER,
|
|
||||||
FOREIGN KEY (show_id) REFERENCES media (id)
|
|
||||||
);
|
|
||||||
''')
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
|
|
||||||
def add_book(title , year, author, page):
|
|
||||||
conn = sqlite3.connect('my_library.db')
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO media (title, type, release_year) VALUES (?, 'Book', ?)", (title, year))
|
|
||||||
last_id = cursor.lastrowid
|
|
||||||
cursor.execute("INSERT INTO books (book_id, author, pages) VALUES (?, ?, ?)", (last_id, author, pages))
|
|
||||||
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
print(f"Added {title} successfully!")
|
|
||||||
|
|
||||||
def add_shows(title , year, network, episodes):
|
|
||||||
conn = sqlite3.connect('my_library')
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
cursor.execute("INSERT INTO media(title, type, release_year) VALUES (?, 'Show',?)" , (title, year))
|
|
||||||
last_id = cursor.lastrowid
|
|
||||||
cursor.execute("INSERT INTO shows(show_id , network , episodes) VALUES (?,?,?)" , (last_id,network,episodes))
|
|
||||||
conn.commit()
|
|
||||||
conn.close()
|
|
||||||
print(f"Added {title} successfully!")
|
|
||||||
|
|
||||||
#fetch
|
|
||||||
def get_all_media():
|
|
||||||
conn = sqlite3.connect('my_library.db')
|
|
||||||
# This line makes results behave like dictionaries (e.g., row['title'])
|
|
||||||
conn.row_factory = sqlite3.Row
|
|
||||||
cursor = conn.cursor()
|
|
||||||
|
|
||||||
query = """
|
|
||||||
SELECT m.title, m.type, b.author, s.network
|
|
||||||
FROM media m
|
|
||||||
LEFT JOIN books b ON m.id = b.book_id
|
|
||||||
LEFT JOIN shows s ON m.id = s.show_id
|
|
||||||
"""
|
|
||||||
|
|
||||||
rows = cursor.execute(query).fetchall()
|
|
||||||
conn.close()
|
|
||||||
return rows
|
|
||||||
|
|
||||||
# Print the results
|
|
||||||
for item in get_all_media():
|
|
||||||
print(f"{item['title']} ({item['type']})")
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
@@ -0,0 +1,45 @@
|
|||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||||
|
gap: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 10px 20px rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card img {
|
||||||
|
width: 100%;
|
||||||
|
height: 320px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
color: white;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-badge {
|
||||||
|
background: var(--book-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-badge {
|
||||||
|
background: var(--show-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.genre-list {
|
||||||
|
display: block;
|
||||||
|
color: #888;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
:root {
|
||||||
|
--ink: #1a1409;
|
||||||
|
--cream: #f5f0e8;
|
||||||
|
--parchment: #ede8dc;
|
||||||
|
--amber: #c8822a;
|
||||||
|
--amber-light: #e8a84a;
|
||||||
|
--sage: #7a8c6e;
|
||||||
|
--rust: #a84832;
|
||||||
|
--muted: #7a7060;
|
||||||
|
--card-bg: #faf7f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#body_page{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color:var(--cream);
|
||||||
|
}
|
||||||
|
#side_bar{
|
||||||
|
background-color:var(--ink);
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content:center;
|
||||||
|
height: 100vh;
|
||||||
|
width: 30vw;
|
||||||
|
}
|
||||||
|
#menu{
|
||||||
|
list-style-type:none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
#menu-button{
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#home_nav{
|
||||||
|
display:flex;
|
||||||
|
flex-direction:row;
|
||||||
|
justify-content:space-around;
|
||||||
|
align-content:center;
|
||||||
|
width:80vw;
|
||||||
|
padding:20px;
|
||||||
|
}
|
||||||
|
#addLog_button{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
gap:8px;
|
||||||
|
background-color:var(--amber);
|
||||||
|
color:white;
|
||||||
|
border:none;
|
||||||
|
border-radius:40px;
|
||||||
|
padding:12px 22px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 4px 14px rgba(200,130,42,0.35);
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#navagtor{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<div class="card">
|
||||||
|
<img src="{{ url_for('static', filename='covers/' + item.image_path) }}" alt="Cover">
|
||||||
|
<div class="content">
|
||||||
|
<span class="badge {{ 'show-badge' if item.type == 'Show' else 'book-badge' }}">
|
||||||
|
{{ item.type }}
|
||||||
|
</span>
|
||||||
|
<h3 style="margin: 10px 0 5px 0;">{{ item.title }}</h3>
|
||||||
|
<span class="genre-list">🏷️ {{ item.genre_list }}</span>
|
||||||
|
|
||||||
|
<p><strong>{{ item.author if item.type == 'Book' else item.network }}</strong></p>
|
||||||
|
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-top: 10px;">
|
||||||
|
<small>Released: {{ item.release_year }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang = "en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<title>Show log</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- CSS -->
|
||||||
|
<link href="{{ url_for('static', filename='css/style.css') }}" rel="stylesheet">
|
||||||
|
<link href="{{ url_for('static', filename='css/card.css') }}" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- JS -->
|
||||||
|
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id = "body_page">
|
||||||
|
<!--might make this entire thing a div-->
|
||||||
|
<div id = "side_bar">
|
||||||
|
<h1>
|
||||||
|
Book and Movie log
|
||||||
|
</h1>
|
||||||
|
<div id = "navagtor">
|
||||||
|
<ul id = "menu">
|
||||||
|
<li>
|
||||||
|
<a href="" id = "menu-button">Dashboard</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="" id = "menu-button">Log</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="" id = "menu-button">Stats</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<!--maybe add a shelve-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--this is where they show the info for the book/ maybe make it into a data base-->
|
||||||
|
<div id ="homepage">
|
||||||
|
<div id = "home_nav">
|
||||||
|
<!--welcome message/ search bar / add button-->
|
||||||
|
<h1>
|
||||||
|
Good evening
|
||||||
|
</h1>
|
||||||
|
<div id = "seach_bar">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id = "addLog_button">
|
||||||
|
+ log a book/show
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--currently reading-->
|
||||||
|
<div id = "currently">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--data-->
|
||||||
|
|
||||||
|
<!--log-->
|
||||||
|
<div>
|
||||||
|
<div id = "log_nav">
|
||||||
|
<h2>
|
||||||
|
My log
|
||||||
|
</h2>
|
||||||
|
<!--more nav button-->
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--the log-->
|
||||||
|
<div class ="container">
|
||||||
|
<div class = "header-secton">
|
||||||
|
<h1>📚 My Library</h1>
|
||||||
|
<form action ="/add" method ="POST" enctype="multipart/form-data">
|
||||||
|
<input type="text" name="title" placeholder="Title" required>
|
||||||
|
<select name="type">
|
||||||
|
<option value="Book">Book</option>
|
||||||
|
<option value="Show">Show</option>
|
||||||
|
</select>
|
||||||
|
<input type="number" name="year" placeholder="Year">
|
||||||
|
<input type="text" name="extra_info" placeholder="Author/Network">
|
||||||
|
<select name="genre_id">
|
||||||
|
{% for g in genres %}
|
||||||
|
<option value="{{ g.id }}">{{ g.name }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<input type="file" name="cover_image">
|
||||||
|
<button type="submit">Add Entry</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
{% for item in items %}
|
||||||
|
{% include 'card.html' %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--data about genera-->
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--Bootstrap Bundle with Popper -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user