Upload 13 files
Browse files- .dockerignore +13 -0
- Dockerfile +34 -0
- app/__pycache__/data.cpython-312.pyc +0 -0
- app/__pycache__/main.cpython-312.pyc +0 -0
- app/__pycache__/models.cpython-312.pyc +0 -0
- app/data.py +25 -0
- app/main.py +45 -0
- app/models.py +8 -0
- requirements.txt +5 -0
- static/css/main.css +54 -0
- templates/base.html +74 -0
- templates/index.html +59 -0
- templates/movie.html +49 -0
.dockerignore
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
*.pyd
|
| 5 |
+
.Python
|
| 6 |
+
env/
|
| 7 |
+
venv/
|
| 8 |
+
.env
|
| 9 |
+
.git
|
| 10 |
+
.gitignore
|
| 11 |
+
.pytest_cache/
|
| 12 |
+
.coverage
|
| 13 |
+
htmlcov/
|
Dockerfile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use Python 3.12 slim image as base
|
| 2 |
+
FROM python:3.12-slim
|
| 3 |
+
|
| 4 |
+
# Set working directory
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
# Set environment variables
|
| 8 |
+
ENV PYTHONDONTWRITEBYTECODE 1
|
| 9 |
+
ENV PYTHONUNBUFFERED 1
|
| 10 |
+
|
| 11 |
+
# Install system dependencies
|
| 12 |
+
RUN apt-get update \
|
| 13 |
+
&& apt-get install -y --no-install-recommends \
|
| 14 |
+
build-essential \
|
| 15 |
+
curl \
|
| 16 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 17 |
+
|
| 18 |
+
# Copy requirements first to leverage Docker cache
|
| 19 |
+
COPY requirements.txt .
|
| 20 |
+
|
| 21 |
+
# Install Python dependencies
|
| 22 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 23 |
+
|
| 24 |
+
# Copy the rest of the application
|
| 25 |
+
COPY . .
|
| 26 |
+
|
| 27 |
+
# Create necessary directories
|
| 28 |
+
RUN mkdir -p static/css
|
| 29 |
+
|
| 30 |
+
# Expose port 7860
|
| 31 |
+
EXPOSE 7860
|
| 32 |
+
|
| 33 |
+
# Command to run the application
|
| 34 |
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"]
|
app/__pycache__/data.cpython-312.pyc
ADDED
|
Binary file (811 Bytes). View file
|
|
|
app/__pycache__/main.cpython-312.pyc
ADDED
|
Binary file (2.3 kB). View file
|
|
|
app/__pycache__/models.cpython-312.pyc
ADDED
|
Binary file (597 Bytes). View file
|
|
|
app/data.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .models import Movie
|
| 2 |
+
|
| 3 |
+
movie_data = [
|
| 4 |
+
Movie(
|
| 5 |
+
title="Rush (2013)",
|
| 6 |
+
embed_url="https://short.icu/N9uHP3Rwd",
|
| 7 |
+
description="The epic rivalry between Formula 1 drivers James Hunt and Niki Lauda.",
|
| 8 |
+
release_year=2013,
|
| 9 |
+
rating=8.1
|
| 10 |
+
),
|
| 11 |
+
Movie(
|
| 12 |
+
title="Inception (2010)",
|
| 13 |
+
embed_url="https://short.icu/example1",
|
| 14 |
+
description="A thief who steals corporate secrets through dream-sharing technology.",
|
| 15 |
+
release_year=2010,
|
| 16 |
+
rating=8.8
|
| 17 |
+
),
|
| 18 |
+
Movie(
|
| 19 |
+
title="The Dark Knight (2008)",
|
| 20 |
+
embed_url="https://short.icu/example2",
|
| 21 |
+
description="Batman faces his greatest challenge as the Joker wreaks havoc on Gotham City.",
|
| 22 |
+
release_year=2008,
|
| 23 |
+
rating=9.0
|
| 24 |
+
)
|
| 25 |
+
]
|
app/main.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Request, Query
|
| 2 |
+
from fastapi.templating import Jinja2Templates
|
| 3 |
+
from fastapi.staticfiles import StaticFiles
|
| 4 |
+
from fastapi.responses import FileResponse
|
| 5 |
+
from pathlib import Path
|
| 6 |
+
from .models import Movie
|
| 7 |
+
from .data import movie_data
|
| 8 |
+
|
| 9 |
+
app = FastAPI(title="Binge")
|
| 10 |
+
|
| 11 |
+
# Create static directory if it doesn't exist
|
| 12 |
+
static_dir = Path("static")
|
| 13 |
+
static_dir.mkdir(exist_ok=True)
|
| 14 |
+
(static_dir / "css").mkdir(exist_ok=True)
|
| 15 |
+
|
| 16 |
+
# Mount static files
|
| 17 |
+
app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
|
| 18 |
+
|
| 19 |
+
# Templates
|
| 20 |
+
templates = Jinja2Templates(directory="templates")
|
| 21 |
+
|
| 22 |
+
@app.get("/")
|
| 23 |
+
async def home(request: Request, search: str | None = Query(None)):
|
| 24 |
+
if search:
|
| 25 |
+
filtered_movies = [
|
| 26 |
+
movie for movie in movie_data
|
| 27 |
+
if search.lower() in movie.title.lower() or
|
| 28 |
+
(movie.description and search.lower() in movie.description.lower())
|
| 29 |
+
]
|
| 30 |
+
else:
|
| 31 |
+
filtered_movies = movie_data
|
| 32 |
+
|
| 33 |
+
return templates.TemplateResponse(
|
| 34 |
+
"index.html",
|
| 35 |
+
{"request": request, "movies": filtered_movies, "search": search}
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
@app.get("/movie/{movie_id}")
|
| 39 |
+
async def movie_detail(request: Request, movie_id: int):
|
| 40 |
+
if 0 <= movie_id < len(movie_data):
|
| 41 |
+
return templates.TemplateResponse(
|
| 42 |
+
"movie.html",
|
| 43 |
+
{"request": request, "movie": movie_data[movie_id]}
|
| 44 |
+
)
|
| 45 |
+
return {"error": "Movie not found"}
|
app/models.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel
|
| 2 |
+
|
| 3 |
+
class Movie(BaseModel):
|
| 4 |
+
title: str
|
| 5 |
+
embed_url: str
|
| 6 |
+
description: str | None = None
|
| 7 |
+
release_year: int | None = None
|
| 8 |
+
rating: float | None = None
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi==0.109.0
|
| 2 |
+
uvicorn==0.27.0
|
| 3 |
+
python-multipart==0.0.6
|
| 4 |
+
jinja2==3.1.3
|
| 5 |
+
pydantic==2.5.3
|
static/css/main.css
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Add any custom CSS here */
|
| 2 |
+
.aspect-w-16 {
|
| 3 |
+
position: relative;
|
| 4 |
+
padding-bottom: 56.25%; /* 16:9 Aspect Ratio */
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
.aspect-w-16 iframe,
|
| 8 |
+
.aspect-w-16 img {
|
| 9 |
+
position: absolute;
|
| 10 |
+
top: 0;
|
| 11 |
+
left: 0;
|
| 12 |
+
width: 100%;
|
| 13 |
+
height: 100%;
|
| 14 |
+
object-fit: cover;
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
/* Smooth scrolling */
|
| 18 |
+
html {
|
| 19 |
+
scroll-behavior: smooth;
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
/* Custom scrollbar */
|
| 23 |
+
::-webkit-scrollbar {
|
| 24 |
+
width: 8px;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
::-webkit-scrollbar-track {
|
| 28 |
+
background: #121212;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
::-webkit-scrollbar-thumb {
|
| 32 |
+
background: #2D2D2D;
|
| 33 |
+
border-radius: 4px;
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
::-webkit-scrollbar-thumb:hover {
|
| 37 |
+
background: #404040;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
/* Text truncation */
|
| 41 |
+
.line-clamp-1 {
|
| 42 |
+
overflow: hidden;
|
| 43 |
+
display: -webkit-box;
|
| 44 |
+
-webkit-line-clamp: 1;
|
| 45 |
+
-webkit-box-orient: vertical;
|
| 46 |
+
}
|
| 47 |
+
|
| 48 |
+
/* Mobile optimizations */
|
| 49 |
+
@media (max-width: 768px) {
|
| 50 |
+
.container {
|
| 51 |
+
padding-left: 16px;
|
| 52 |
+
padding-right: 16px;
|
| 53 |
+
}
|
| 54 |
+
}
|
templates/base.html
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>{% block title %}Binge{% endblock %}</title>
|
| 7 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<link rel="stylesheet" href="{{ url_for('static', path='/css/main.css') }}">
|
| 9 |
+
<script>
|
| 10 |
+
tailwind.config = {
|
| 11 |
+
theme: {
|
| 12 |
+
extend: {
|
| 13 |
+
colors: {
|
| 14 |
+
dark: '#121212',
|
| 15 |
+
'dark-lighter': '#1E1E1E',
|
| 16 |
+
'dark-accent': '#2D2D2D',
|
| 17 |
+
}
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
}
|
| 21 |
+
</script>
|
| 22 |
+
</head>
|
| 23 |
+
<body class="bg-dark text-white min-h-screen flex flex-col">
|
| 24 |
+
<!-- Mobile-first navigation -->
|
| 25 |
+
<nav class="bg-dark-lighter fixed w-full top-0 z-50 border-b border-dark-accent">
|
| 26 |
+
<div class="container mx-auto px-4 py-3">
|
| 27 |
+
<div class="flex items-center justify-between">
|
| 28 |
+
<a href="/" class="text-2xl font-bold tracking-tighter">BINGE</a>
|
| 29 |
+
<button id="menuBtn" class="md:hidden p-2">
|
| 30 |
+
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 31 |
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-16 6h16"></path>
|
| 32 |
+
</svg>
|
| 33 |
+
</button>
|
| 34 |
+
<div class="hidden md:flex space-x-6">
|
| 35 |
+
<a href="/" class="hover:text-gray-300 transition-colors">Home</a>
|
| 36 |
+
<a href="#" class="hover:text-gray-300 transition-colors">Movies</a>
|
| 37 |
+
<a href="#" class="hover:text-gray-300 transition-colors">TV Shows</a>
|
| 38 |
+
</div>
|
| 39 |
+
</div>
|
| 40 |
+
</div>
|
| 41 |
+
</nav>
|
| 42 |
+
|
| 43 |
+
<!-- Mobile menu -->
|
| 44 |
+
<div id="mobileMenu" class="hidden fixed inset-0 bg-dark z-40 pt-16">
|
| 45 |
+
<div class="container mx-auto px-4 py-6">
|
| 46 |
+
<div class="flex flex-col space-y-4">
|
| 47 |
+
<a href="/" class="text-lg hover:text-gray-300 transition-colors">Home</a>
|
| 48 |
+
<a href="#" class="text-lg hover:text-gray-300 transition-colors">Movies</a>
|
| 49 |
+
<a href="#" class="text-lg hover:text-gray-300 transition-colors">TV Shows</a>
|
| 50 |
+
</div>
|
| 51 |
+
</div>
|
| 52 |
+
</div>
|
| 53 |
+
|
| 54 |
+
<main class="container mx-auto px-4 py-8 mt-16 flex-grow">
|
| 55 |
+
{% block content %}{% endblock %}
|
| 56 |
+
</main>
|
| 57 |
+
|
| 58 |
+
<footer class="bg-dark-lighter py-6 mt-auto">
|
| 59 |
+
<div class="container mx-auto px-4 text-center text-sm text-gray-400">
|
| 60 |
+
<p>© 2024 Binge. All rights reserved.</p>
|
| 61 |
+
</div>
|
| 62 |
+
</footer>
|
| 63 |
+
|
| 64 |
+
<script>
|
| 65 |
+
// Mobile menu toggle
|
| 66 |
+
const menuBtn = document.getElementById('menuBtn');
|
| 67 |
+
const mobileMenu = document.getElementById('mobileMenu');
|
| 68 |
+
|
| 69 |
+
menuBtn.addEventListener('click', () => {
|
| 70 |
+
mobileMenu.classList.toggle('hidden');
|
| 71 |
+
});
|
| 72 |
+
</script>
|
| 73 |
+
</body>
|
| 74 |
+
</html>
|
templates/index.html
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% extends "base.html" %}
|
| 2 |
+
|
| 3 |
+
{% block title %}Binge - Watch Movies Online{% endblock %}
|
| 4 |
+
|
| 5 |
+
{% block content %}
|
| 6 |
+
<div class="space-y-8">
|
| 7 |
+
<!-- Search bar -->
|
| 8 |
+
<div class="max-w-2xl mx-auto mb-12">
|
| 9 |
+
<form action="/" method="get" class="relative">
|
| 10 |
+
<input
|
| 11 |
+
type="search"
|
| 12 |
+
name="search"
|
| 13 |
+
placeholder="Search movies..."
|
| 14 |
+
value="{{ search or '' }}"
|
| 15 |
+
class="w-full bg-dark-lighter border border-dark-accent rounded-lg px-4 py-3 pl-12 focus:outline-none focus:border-gray-500 transition-colors"
|
| 16 |
+
>
|
| 17 |
+
<svg class="w-6 h-6 text-gray-400 absolute left-3 top-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
| 18 |
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
| 19 |
+
</svg>
|
| 20 |
+
</form>
|
| 21 |
+
</div>
|
| 22 |
+
|
| 23 |
+
{% if not movies %}
|
| 24 |
+
<div class="text-center py-12">
|
| 25 |
+
<p class="text-gray-400">No movies found. Try a different search.</p>
|
| 26 |
+
</div>
|
| 27 |
+
{% else %}
|
| 28 |
+
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
| 29 |
+
{% for movie in movies %}
|
| 30 |
+
<div class="bg-dark-lighter rounded-lg overflow-hidden shadow-lg transform hover:scale-105 transition-transform duration-200">
|
| 31 |
+
<a href="/movie/{{ loop.index0 }}" class="block">
|
| 32 |
+
<div class="aspect-w-16 aspect-h-9 bg-dark-accent">
|
| 33 |
+
<img
|
| 34 |
+
src="https://via.placeholder.com/300x450"
|
| 35 |
+
alt="{{ movie.title }}"
|
| 36 |
+
class="w-full h-full object-cover opacity-90 hover:opacity-100 transition-opacity"
|
| 37 |
+
>
|
| 38 |
+
</div>
|
| 39 |
+
<div class="p-4 space-y-2">
|
| 40 |
+
<h2 class="text-lg font-semibold line-clamp-1">{{ movie.title }}</h2>
|
| 41 |
+
{% if movie.release_year %}
|
| 42 |
+
<p class="text-sm text-gray-400">{{ movie.release_year }}</p>
|
| 43 |
+
{% endif %}
|
| 44 |
+
{% if movie.rating %}
|
| 45 |
+
<div class="flex items-center">
|
| 46 |
+
<svg class="w-5 h-5 text-yellow-500" fill="currentColor" viewBox="0 0 20 20">
|
| 47 |
+
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
|
| 48 |
+
</svg>
|
| 49 |
+
<span class="ml-1 text-sm">{{ movie.rating }}/10</span>
|
| 50 |
+
</div>
|
| 51 |
+
{% endif %}
|
| 52 |
+
</div>
|
| 53 |
+
</a>
|
| 54 |
+
</div>
|
| 55 |
+
{% endfor %}
|
| 56 |
+
</div>
|
| 57 |
+
{% endif %}
|
| 58 |
+
</div>
|
| 59 |
+
{% endblock %}
|
templates/movie.html
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{% extends "base.html" %}
|
| 2 |
+
|
| 3 |
+
{% block title %}{{ movie.title }} - Binge{% endblock %}
|
| 4 |
+
|
| 5 |
+
{% block content %}
|
| 6 |
+
<div class="max-w-4xl mx-auto space-y-8">
|
| 7 |
+
<div class="flex flex-col md:flex-row md:items-start md:space-x-8">
|
| 8 |
+
<div class="w-full md:w-2/3">
|
| 9 |
+
<div class="aspect-w-16 aspect-h-9 bg-dark-lighter rounded-lg overflow-hidden shadow-lg">
|
| 10 |
+
<iframe
|
| 11 |
+
src="{{ movie.embed_url }}"
|
| 12 |
+
frameborder="0"
|
| 13 |
+
scrolling="0"
|
| 14 |
+
allowfullscreen
|
| 15 |
+
class="w-full h-full"
|
| 16 |
+
></iframe>
|
| 17 |
+
</div>
|
| 18 |
+
</div>
|
| 19 |
+
|
| 20 |
+
<div class="w-full md:w-1/3 mt-6 md:mt-0">
|
| 21 |
+
<h1 class="text-2xl font-bold mb-4">{{ movie.title }}</h1>
|
| 22 |
+
|
| 23 |
+
<div class="flex items-center space-x-4 mb-6">
|
| 24 |
+
{% if movie.release_year %}
|
| 25 |
+
<div class="bg-dark-lighter px-3 py-1 rounded text-sm">
|
| 26 |
+
{{ movie.release_year }}
|
| 27 |
+
</div>
|
| 28 |
+
{% endif %}
|
| 29 |
+
|
| 30 |
+
{% if movie.rating %}
|
| 31 |
+
<div class="bg-dark-lighter px-3 py-1 rounded flex items-center">
|
| 32 |
+
<svg class="w-4 h-4 text-yellow-500" fill="currentColor" viewBox="0 0 20 20">
|
| 33 |
+
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
|
| 34 |
+
</svg>
|
| 35 |
+
<span class="ml-1">{{ movie.rating }}/10</span>
|
| 36 |
+
</div>
|
| 37 |
+
{% endif %}
|
| 38 |
+
</div>
|
| 39 |
+
|
| 40 |
+
{% if movie.description %}
|
| 41 |
+
<div class="bg-dark-lighter p-4 rounded-lg">
|
| 42 |
+
<h2 class="text-lg font-semibold mb-2">About</h2>
|
| 43 |
+
<p class="text-gray-300 text-sm">{{ movie.description }}</p>
|
| 44 |
+
</div>
|
| 45 |
+
{% endif %}
|
| 46 |
+
</div>
|
| 47 |
+
</div>
|
| 48 |
+
</div>
|
| 49 |
+
{% endblock %}
|