Skip to content
Merged

Dev #98

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added frontend/src/assets/grppic.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions frontend/src/components/Footer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ export default function Footer() {
.catch(() => setGotQuote(null));
}, []);

// Function to scroll to top
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
};

return (
<footer className="bg-gray-100 dark:bg-black border-t border-gray-300 dark:border-gray-800 mt-auto">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
Expand Down Expand Up @@ -60,6 +68,7 @@ export default function Footer() {
<li>
<Link
to="/about"
onClick={scrollToTop}
className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors text-sm"
>
About Us
Expand All @@ -68,6 +77,7 @@ export default function Footer() {
<li>
<Link
to="/contact"
onClick={scrollToTop}
className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors text-sm"
>
Contact
Expand All @@ -76,6 +86,7 @@ export default function Footer() {
<li>
<Link
to="/terms"
onClick={scrollToTop}
className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors text-sm"
>
Terms of Service
Expand All @@ -84,6 +95,7 @@ export default function Footer() {
<li>
<Link
to="/privacy"
onClick={scrollToTop}
className="text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors text-sm"
>
Privacy Policy
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/Navbar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const Navbar = () => {
const NavLinks = () => (
<>
<Link to="/" className="text-gray-200 hover:text-white px-3 py-1 rounded-md transition" onClick={() => setDrawerOpen(false)}>Home</Link>
<Link to="/ai" className="text-gray-200 hover:text-white px-3 py-1 rounded-md transition" onClick={() => setDrawerOpen(false)}>AI</Link>
{logged && (
<Link to="/ai" className="text-gray-200 hover:text-white px-3 py-1 rounded-md transition" onClick={() => setDrawerOpen(false)}>AI</Link>
)}
{logged && user && (
<>
<Link to="/forum" className="text-gray-200 hover:text-white px-3 py-1 rounded-md transition" onClick={() => setDrawerOpen(false)}>Forum</Link>
Expand Down
71 changes: 57 additions & 14 deletions frontend/src/pages/Contact.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import {
FaFacebook,
FaInstagram
} from 'react-icons/fa';
import teamPhoto from '../assets/grppic.jpg';

export default function Contact() {
const teamMembers = [
{
name: "Sakibul Hassan Shovon",
role: "Full Stack Developer & Project Lead",
email: "shovon@redpill.com",
email: "sakibulhassan.shovon@redpill.com",
github: "https://github.com/sakibul-shovon",
linkedin: "https://linkedin.com/in/sakibul-hassan-shovon",
twitter: "https://twitter.com/shovon_dev",
Expand Down Expand Up @@ -69,22 +70,47 @@ export default function Contact() {
</p>
</motion.div>

{/* Team Section */}
{/* Team Photo Section */}
<motion.div
variants={containerVariants}
initial="hidden"
animate="visible"
className="mb-16"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="mb-12"
>
<div className="text-center mb-8">
<h2 className="text-3xl lg:text-4xl font-bold mb-4 text-gray-900 dark:text-white">
Meet the{' '}
<span className="bg-gradient-to-r from-red-500 to-red-700 text-transparent bg-clip-text">
Developers
</span>
</h2>
<p className="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
The creative minds behind RedPill
</p>
</div>

<div className="flex justify-center">
<div className="relative group">
<img
src={teamPhoto}
alt="RedPill Development Team - Shovon & Zawad"
className="w-full max-w-2xl mx-auto rounded-2xl shadow-lg object-cover h-64 md:h-80 lg:h-96"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/10 to-transparent rounded-2xl"></div>
</div>
</div>
</motion.div>

{/* Team Section */}
<div className="mb-16">
<h2 className="text-3xl font-bold text-center mb-12 text-gray-900 dark:text-white">
Our Team
</h2>

<div className="grid md:grid-cols-2 gap-8">
{teamMembers.map((member, index) => (
<motion.div
{teamMembers && teamMembers.length > 0 ? teamMembers.map((member, index) => (
<div
key={index}
variants={itemVariants}
className="bg-gray-50 dark:bg-gray-900 rounded-xl p-8 border border-gray-200 dark:border-gray-800 hover:shadow-xl transition-all duration-300"
>
<div className="text-center mb-6">
Expand Down Expand Up @@ -156,11 +182,28 @@ export default function Contact() {
>
<FaTwitter className="w-5 h-5" />
</a>
<a
href={member.name === "Sakibul Hassan Shovon"
? "https://www.facebook.com/sakibulhassanshovon05/"
: member.name === "Md. Iftekhar Zawad"
? "https://www.facebook.com/md.iftekhar.zawad"
: `https://facebook.com/${member.name.toLowerCase().replace(/\s+/g, '.')}`}
target="_blank"
rel="noopener noreferrer"
className="p-3 bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 rounded-full hover:bg-blue-200 dark:hover:bg-blue-900/50 transition-colors"
title="Facebook"
>
<FaFacebook className="w-5 h-5" />
</a>
</div>
</motion.div>
))}
</div>
)) : (
<div className="col-span-2 text-center text-gray-500">
<p>Team information loading...</p>
</div>
)}
</div>
</motion.div>
</div>

{/* Contact Information */}
<motion.div
Expand All @@ -172,8 +215,8 @@ export default function Contact() {
<div className="text-center p-6 bg-gray-50 dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800">
<FaEnvelope className="w-8 h-8 text-red-600 dark:text-red-400 mx-auto mb-4" />
<h3 className="text-xl font-semibold mb-2 text-gray-900 dark:text-white">Email Us</h3>
<p className="text-gray-600 dark:text-gray-400">support@redpill.com</p>
<p className="text-gray-600 dark:text-gray-400">contact@redpill.com</p>
<p className="text-gray-600 dark:text-gray-400">shovon.cse50@gmail.com</p>
<p className="text-gray-600 dark:text-gray-400">md.iftekharzawad@gmail.com</p>
</div>

<div className="text-center p-6 bg-gray-50 dark:bg-gray-900 rounded-xl border border-gray-200 dark:border-gray-800">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/Landing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ export default function Landing() {

<div className="mt-5 flex flex-wrap gap-3 items-center">
<Link to={`/movies/${featured.id}`} className="px-4 xs:px-5 py-2 rounded-md bg-yellow-400 text-black font-semibold shadow hover:bg-yellow-300 text-sm xs:text-base">View Details</Link>
<Link to="/discover" className="px-3 xs:px-4 py-2 rounded-md bg-white/10 border border-gray-200 dark:border-white/20 text-white dark:text-white hover:bg-white/15 text-sm xs:text-base">Discover More</Link>
<Link to="/search?genre=1" className="px-3 xs:px-4 py-2 rounded-md bg-white/10 border border-gray-200 dark:border-white/20 text-white dark:text-white hover:bg-white/15 text-sm xs:text-base">Discover More</Link>
</div>
</div>
</motion.div>
Expand Down
15 changes: 4 additions & 11 deletions frontend/src/pages/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,17 @@ export default function Login() {
};

return (
<div className="relative min-h-screen flex items-center justify-center overflow-hidden bg-gray-900 text-gray-100 px-4">
{/* Movie poster background - Her (2013) */}
<div className="absolute inset-0 -z-20 bg-cover bg-center" style={{
backgroundImage: "url('/src/assets/loginImage.jpg')"
}} />
{/* Dark overlay for readability */}
<div className="absolute inset-0 -z-10 bg-black/70" />

<div className="relative min-h-screen flex flex-col items-center justify-center overflow-hidden bg-gray-100 dark:bg-[#181e2a] transition-colors duration-300">
{/* Main card */}
<motion.div
initial={{ opacity: 0, y: 20, scale: 0.98 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{ duration: 0.5, ease: "easeOut" }}
className="w-full max-w-md"
>
<div className="relative rounded-2xl border border-white/10 bg-black/60 backdrop-blur-xl shadow-2xl p-8">
<div className="relative rounded-2xl border border-white/20 bg-black/40 backdrop-blur-2xl shadow-2xl p-8 ring-1 ring-white/10">
{/* Subtle glow effect */}
<div className="absolute inset-0 rounded-2xl bg-gradient-to-br from-red-500/10 via-transparent to-red-500/5 pointer-events-none"></div>
{/* Branding */}
<motion.div
initial={{ opacity: 0, y: 8 }}
Expand All @@ -67,8 +62,6 @@ export default function Login() {
<h1 className="text-3xl font-extrabold tracking-tight text-white">RedPill</h1>
<p className="mt-2 text-sm text-gray-300">Enter the cinematic universe 🎬</p>
</motion.div>

{/* Error display */}
<AnimatePresence>
{error && (
<motion.div
Expand Down
63 changes: 32 additions & 31 deletions frontend/src/pages/MovieDetails.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,17 @@ function Pill({ children }) {
function KeyVal({ k, v }) {
return (
<div className="flex gap-3 text-sm">
<div className="min-w-[120px] text-gray-500 dark:text-gray-400">{k}</div>
<div className="text-gray-700 dark:text-gray-200 flex-1">{v || "—"}</div>
<div className="min-w-[120px] text-gray-300">{k}</div>
<div className="text-gray-100 flex-1">{v || "—"}</div>
</div>
);
}

function DetailsKeyVal({ k, v }) {
return (
<div className="flex gap-3 text-sm">
<div className="min-w-[120px] text-gray-600 dark:text-gray-400">{k}</div>
<div className="text-gray-900 dark:text-gray-200 flex-1">{v || "—"}</div>
</div>
);
}
Expand Down Expand Up @@ -536,9 +545,9 @@ export default function MovieDetail() {
src={img.backdrop(hero.backdrop_path)}
alt={hero.title}
className="absolute inset-0 w-full h-full object-cover"
style={{ filter: "brightness(0.55)" }}
style={{ filter: "brightness(0.4)" }}
/>
<div className="absolute inset-0 bg-gradient-to-b from-white/0 dark:from-black/10 via-black/50 to-black/85" />
<div className="absolute inset-0 bg-gradient-to-b from-black/30 via-black/60 to-black/90 dark:from-black/10 dark:via-black/50 dark:to-black/85" />

<div className="relative z-10 max-w-7xl mx-auto px-6 py-10 grid grid-cols-1 md:grid-cols-[260px,1fr] gap-6 pt-24">
{/* Poster */}
Expand Down Expand Up @@ -591,9 +600,9 @@ export default function MovieDetail() {
<div className="flex flex-wrap items-center gap-2 mb-2">
<Pill>Top pick</Pill>
</div>
<h1 className="text-gray-900 dark:text-white text-4xl md:text-5xl font-extrabold tracking-tight">{hero.title}</h1>
<h1 className="text-white text-4xl md:text-5xl font-extrabold tracking-tight">{hero.title}</h1>

<div className="mt-3 flex flex-wrap items-center gap-3 text-gray-600 dark:text-gray-300">
<div className="mt-3 flex flex-wrap items-center gap-3 text-gray-200">
<span>{yearOf(hero)}</span>
<span>•</span>
<span>{runtimeOf(hero.runtime)}</span>
Expand Down Expand Up @@ -657,7 +666,7 @@ export default function MovieDetail() {
<button onClick={() => navigator?.share && navigator.share({ title: hero.title, url: window.location.href })} className="px-3 py-1.5 rounded bg-gray-100/6 dark:bg-white/5 border border-gray-200/5 dark:border-white/20 text-sm hover:bg-gray-100/20">Share</button>
</div> {/* Synopsis */}
{hero.overview ? (
<p className="mt-5 text-gray-700 dark:text-gray-200 leading-relaxed max-w-3xl">{hero.overview}</p>
<p className="mt-5 text-gray-100 leading-relaxed max-w-3xl">{hero.overview}</p>
) : null}

{/* Credits small */}
Expand Down Expand Up @@ -734,10 +743,10 @@ export default function MovieDetail() {

{/* AI Summary Section */}
<section className="mb-10">
<div className="relative rounded-2xl bg-gradient-to-b from-black/80 to-black/40 dark:from-white/5 dark:to-white/0 backdrop-blur-sm border border-white/10 p-6 overflow-hidden group">
<div className="relative rounded-2xl bg-gradient-to-b from-gray-50 to-gray-100/50 dark:from-gray-900/80 dark:to-gray-800/40 backdrop-blur-sm border border-gray-300 dark:border-gray-600 p-6 overflow-hidden group shadow-md ring-1 ring-gray-200 dark:ring-gray-700">
{/* Background effects */}
<div className="absolute inset-0 bg-gradient-to-r from-indigo-500/10 via-purple-500/10 to-pink-500/10 dark:from-indigo-500/5 dark:via-purple-500/5 dark:to-pink-500/5 opacity-40"></div>
<div className="absolute inset-0 bg-gradient-to-br from-black/20 to-transparent dark:from-white/5"></div>
<div className="absolute inset-0 bg-gradient-to-r from-indigo-500/5 via-purple-500/5 to-pink-500/5 dark:from-indigo-500/10 dark:via-purple-500/10 dark:to-pink-500/10 opacity-40"></div>
<div className="absolute inset-0 bg-gradient-to-br from-gray-200/10 to-transparent dark:from-gray-900/20 dark:to-transparent"></div>

{/* Header */}
<div className="relative flex items-center justify-between mb-6">
Expand All @@ -748,8 +757,8 @@ export default function MovieDetail() {
</svg>
</div>
<div>
<h2 className="text-lg md:text-xl font-bold bg-gradient-to-r from-indigo-200 to-purple-200 dark:from-indigo-200 dark:to-purple-200 text-transparent bg-clip-text">AI-Powered Insights</h2>
<p className="text-sm text-gray-500 dark:text-gray-400">Discover unique perspectives on this film</p>
<h2 className="text-lg md:text-xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 dark:from-indigo-200 dark:to-purple-200 text-transparent bg-clip-text">AI-Powered Insights</h2>
<p className="text-sm text-gray-600 dark:text-gray-400">Discover unique perspectives on this film</p>
</div>
</div>

Expand Down Expand Up @@ -787,7 +796,7 @@ export default function MovieDetail() {
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="text-gray-500 dark:text-gray-400 text-sm"
className="text-gray-600 dark:text-gray-400 text-sm"
>
Click 'Generate AI Summary' to get an AI-powered analysis of this film.
</motion.div>
Expand All @@ -798,7 +807,7 @@ export default function MovieDetail() {
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="flex items-center gap-3 text-gray-500 dark:text-gray-400"
className="flex items-center gap-3 text-gray-600 dark:text-gray-400"
>
<div className="w-2 h-2 rounded-full bg-indigo-500 animate-ping"></div>
<div className="w-2 h-2 rounded-full bg-purple-500 animate-ping [animation-delay:0.2s]"></div>
Expand All @@ -815,7 +824,7 @@ export default function MovieDetail() {
transition={{ duration: 0.3 }}
className="relative"
>
<div className="relative text-gray-700 dark:text-gray-200 leading-relaxed text-base">
<div className="relative text-gray-800 dark:text-gray-200 leading-relaxed text-base">
<TypewriterEffect
text={aiSummary}
onComplete={() => setIsTypingComplete(true)}
Expand Down Expand Up @@ -856,14 +865,14 @@ export default function MovieDetail() {
<section className="mb-10">
<h2 className="text-gray-900 dark:text-white text-lg md:text-xl font-semibold mb-3">Details</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 rounded-2xl bg-gray-100/6 dark:bg-white/5 border border-gray-200/5 dark:border-white/10 p-5">
<KeyVal k="Status" v={movie?.status} />
<KeyVal k="Original Title" v={movie?.original_title} />
<KeyVal k="Release" v={movie?.release_date ? new Date(movie.release_date).toLocaleDateString() : "—"} />
<KeyVal k="Runtime" v={runtimeOf(movie?.runtime)} />
<KeyVal k="Budget" v={money(movie?.budget)} />
<KeyVal k="Revenue" v={money(movie?.revenue)} />
<KeyVal k="Production" v={movie?.production_companies?.map((c) => c.name).join(", ")} />
<KeyVal k="Countries" v={movie?.production_countries?.map((c) => c.name).join(", ")} />
<DetailsKeyVal k="Status" v={movie?.status} />
<DetailsKeyVal k="Original Title" v={movie?.original_title} />
<DetailsKeyVal k="Release" v={movie?.release_date ? new Date(movie.release_date).toLocaleDateString() : "—"} />
<DetailsKeyVal k="Runtime" v={runtimeOf(movie?.runtime)} />
<DetailsKeyVal k="Budget" v={money(movie?.budget)} />
<DetailsKeyVal k="Revenue" v={money(movie?.revenue)} />
<DetailsKeyVal k="Production" v={movie?.production_companies?.map((c) => c.name).join(", ")} />
<DetailsKeyVal k="Countries" v={movie?.production_countries?.map((c) => c.name).join(", ")} />
</div>
</section>

Expand All @@ -881,14 +890,6 @@ export default function MovieDetail() {
</RowScroller>
</section>
) : null}

{/* FOOTER CTA */}
<div className="mt-12 text-center">
<Link to="/discover" className="inline-flex items-center gap-2 px-5 py-2 rounded-md bg-gray-100/6 dark:bg-white/5 border border-gray-200/5 dark:border-white/10 text-gray-900 dark:text-white hover:bg-gray-100/20">
Discover more titles
<svg width="16" height="16" viewBox="0 0 24 24"><path fill="currentColor" d="M13 5.83 14.17 7l-4.88 4.88L7 10.71zm0 12.34 6-6-6-6L17 7.17 12.17 12 17 16.83z"/></svg>
</Link>
</div>
</div>

{/* USER REVIEWS (last section) */}
Expand Down
Loading