JIT
building an anime and tv series tracker web application
Project Overview: The web app development team has been assigned the task of building an Anime & TV Series Tracker web application. This tool will allow users to efficiently manage their anime and TV series watchlists while engaging in discussions with other fans through community features. The interns are responsible for completing it within the given timeline. Project Objectives: 1. Develop an intuitive web-based platform for tracking anime and TV series progress. 2. Enable tracking of watched and pending episodes. 3. Provide an interactive and community-driven experience through custom clubs. 4. Ensure a smooth and responsive user interface. 5. Implement AI-powered recommendations based on user preferences. Core Features Developed: 1. Menu Categories: Users can organize shows under: o All o Watching o Completed o On Hold o Dropped o Plan to Watch 2. Progress Tracking: Users can log watched episodes and track remaining episodes. 3. Custom Clubs & Discussion Boards: Users can create/join groups to discuss shows. 4. Spoiler Protection: Users can choose to hide/reveal spoilers. 5. Polls & Ratings: Club members can vote on episodes, characters, and storylines. 6. User Reviews & Comments: Users can leave reviews on specific shows. 7. Episode & Season Reminders: Alerts for upcoming episodes or scheduled watch times. 8. Streaming Integration: Direct links to streaming platforms where shows are available. 9. Watchlist Sharing: Users can share their lists with friends and community members. 10. Dark & Light Mode: Custom themes for personalized user experience. 11. Tags & Filters: Users can filter by genre, language, release year, etc. 12. Analytics Dashboard: Graphs and insights on watch history and time spent. 13. Admin Panel: Web-based control panel for managing discussions and user interactions. give total frontend and backe end for the application of webpage directly so that i can preview it

I'll help you create a comprehensive Anime & TV Series Tracker web application. Here's the initial setup with both frontend and backend components:

<jitProject id="anime-tracker-app" title="Anime & TV Series Tracker"> <jitFile type="file" filePath="package.json"> { "name": "anime-tracker", "version": "1.0.0", "description": "Anime & TV Series Tracker Application", "main": "server.js", "scripts": { "start": "node server.js", "dev": "nodemon server.js" }, "dependencies": { "express": "^4.18.2", "mongoose": "^8.0.3", "cors": "^2.8.5", "dotenv": "^16.3.1", "bcryptjs": "^2.4.3", "jsonwebtoken": "^9.0.2", "socket.io": "^4.7.2" }, "devDependencies": { "nodemon": "^3.0.2" } } </jitFile> <jitFile type="file" filePath="server.js"> const express = require('express'); const mongoose = require('mongoose'); const cors = require('cors'); const dotenv = require('dotenv'); const userRoutes = require('./routes/userRoutes'); const animeRoutes = require('./routes/animeRoutes'); const clubRoutes = require('./routes/clubRoutes');

dotenv.config(); const app = express();

// Middleware app.use(cors()); app.use(express.json());

// Database connection mongoose.connect(process.env.MONGODB_URI) .then(() => console.log('Connected to MongoDB')) .catch(err => console.error('MongoDB connection error:', err));

// Routes app.use('/api/users', userRoutes); app.use('/api/anime', animeRoutes); app.use('/api/clubs', clubRoutes);

// Start server const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(Server running on port ${PORT}); }); </jitFile>

<jitFile type="file" filePath="routes/userRoutes.js"> const express = require('express'); const router = express.Router(); const User = require('../models/User'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken');

// User registration router.post('/register', async (req, res) => { try { const { username, email, password } = req.body; const hashedPassword = await bcrypt.hash(password, 10); const user = new User({ username, email, password: hashedPassword }); await user.save(); res.status(201).json({ message: 'User created successfully' }); } catch (error) { res.status(500).json({ error: error.message }); } });

// User login router.post('/login', async (req, res) => { try { const { email, password } = req.body; const user = await User.findOne({ email }); if (!user) return res.status(404).json({ error: 'User not found' });

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) return res.status(400).json({ error: 'Invalid credentials' });

const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({ token, user: { id: user._id, username: user.username, email: user.email } });

} catch (error) { res.status(500).json({ error: error.message }); } });

module.exports = router; </jitFile>

<jitFile type="file" filePath="routes/animeRoutes.js"> const express = require('express'); const router = express.Router(); const Anime = require('../models/Anime'); const auth = require('../middleware/auth');

// Get all anime router.get('/', auth, async (req, res) => { try { const animeList = await Anime.find(); res.json(animeList); } catch (error) { res.status(500).json({ error: error.message }); } });

// Add new anime router.post('/', auth, async (req, res) => { try { const anime = new Anime(req.body); await anime.save(); res.status(201).json(anime); } catch (error) { res.status(500).json({ error: error.message }); } });

module.exports = router; </jitFile>

<jitFile type="file" filePath="routes/clubRoutes.js"> const express = require('express'); const router = express.Router(); const Club = require('../models/Club'); const auth = require('../middleware/auth');

// Create club router.post('/', auth, async (req, res) => { try { const club = new Club({ ...req.body, creator: req.user.id }); await club.save(); res.status(201).json(club); } catch (error) { res.status(500).json({ error: error.message }); } });

// Get all clubs router.get('/', auth, async (req, res) => { try { const clubs = await Club.find().populate('creator', 'username'); res.json(clubs); } catch (error) { res.status(500).json({ error: error.message }); } });

module.exports = router; </jitFile>

<jitFile type="file" filePath="models/User.js"> const mongoose = require('mongoose'); const bcrypt = require('bcryptjs');

const userSchema = new mongoose.Schema({ username: { type: String, required: true, unique: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, watchlist: [{ animeId: { type: mongoose.Schema.Types.ObjectId, ref: 'Anime' }, status: { type: String, enum: ['watching', 'completed', 'on-hold', 'dropped', 'plan-to-watch'], default: 'plan-to-watch' }, progress: { type: Number, default: 0 }, rating: { type: Number, min: 1, max: 10 } }], createdAt: { type: Date, default: Date.now } });

userSchema.pre('save', async function(next) { if (this.isModified('password')) { this.password = await bcrypt.hash(this.password, 10); } next(); });

module.exports = mongoose.model('User', userSchema); </jitFile>

<jitFile type="file" filePath="models/Anime.js"> const mongoose = require('mongoose');

const animeSchema = new mongoose.Schema({ title: { type: String, required: true }, description: { type: String, required: true }, imageUrl: { type: String, required: true }, episodes: { type: Number, required: true }, status: { type: String, enum: ['airing', 'completed', 'upcoming'], required: true }, genres: [{ type: String }], season: { type: String }, year: { type: Number }, rating: { type: Number, default: 0 }, reviews: [{ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, content: { type: String }, rating: { type: Number, min: 1, max: 10 }, createdAt: { type: Date, default: Date.now } }] });

module.exports = mongoose.model('Anime', animeSchema); </jitFile>

<jitFile type="file" filePath="models/Club.js"> const mongoose = require('mongoose');

const clubSchema = new mongoose.Schema({ name: { type: String, required: true }, description: { type: String, required: true }, animeId: { type: mongoose.Schema.Types.ObjectId, ref: 'Anime' }, creator: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true }, members: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }], discussions: [{ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, content: { type: String, required: true }, isSpoiler: { type: Boolean, default: false }, createdAt: { type: Date, default: Date.now }, replies: [{ userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, content: { type: String, required: true }, createdAt: { type: Date, default: Date.now } }] }], polls: [{ question: { type: String, required: true }, options: [{ text: { type: String, required: true }, votes: { type: Number, default: 0 } }], createdAt: { type: Date, default: Date.now } }], createdAt: { type: Date, default: Date.now } });

module.exports = mongoose.model('Club', clubSchema); </jitFile>

<jitFile type="file" filePath="middleware/auth.js"> const jwt = require('jsonwebtoken');

module.exports = function(req, res, next) { const token = req.header('Authorization')?.replace('Bearer ', ''); if (!token) return res.status(401).json({ error: 'Access denied. No token provided.' });

try { const decoded = jwt.verify(token, process.env.JWT_SECRET); req.user = decoded; next(); } catch (error) { res.status(400).json({ error: 'Invalid token.' }); } }; </jitFile>

<jitFile type="file" filePath="public/index.html"> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Anime & TV Series Tracker</title> <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> <link rel="stylesheet" href="/css/styles.css"> </head> <body class="bg-gray-100 dark:bg-gray-900"> <div id="app" class="min-h-screen"> <!-- Navbar --> <nav class="bg-indigo-600 text-white p-4 shadow-md"> <div class="container mx-auto flex justify-between items-center"> <h1 class="text-2xl font-bold">AnimeTracker</h1> <div class="flex items-center space-x-4"> <button id="theme-toggle" class="p-2 rounded-full hover:bg-indigo-700"> <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> </svg> </button> <button id="login-btn" class="px-4 py-2 rounded bg-indigo-700 hover:bg-indigo-800">Login</button> </div> </div> </nav>
<!-- Main Content -->
<main class="container mx-auto p-4">
  <div class="grid grid-cols-1 md:grid-cols-4 gap-4">
    <!-- Sidebar -->
    <aside class="md:col-span-1 bg-white dark:bg-gray-800 rounded-lg shadow p-4">
      <h2 class="text-xl font-semibold mb-4 dark:text-white">Menu</h2>
      <ul class="space-y-2">
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">All</a></li>
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">Watching</a></li>
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">Completed</a></li>
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">On Hold</a></li>
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">Dropped</a></li>
        <li><a href="#" class="menu-item block p-2 rounded hover:bg-indigo-100 dark:hover:bg-gray-700 dark:text-white">Plan to Watch</a></li>
      </ul>
    </aside>

    <!-- Content Area -->
    <div class="md:col-span-3">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-4">
        <h2 class="text-xl font-semibold mb-4 dark:text-white">My Watchlist</h2>
        <div id="anime-list" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
          <!-- Anime cards will be loaded here -->
        </div>
      </div>
    </div>
  </div>
</main>
</div> <!-- Modals --> <div id="login-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center"> <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md"> <h2 class="text-2xl font-bold mb-4 dark:text-white">Login</h2> <form id="login-form"> <div class="mb-4"> <label class="block text-gray-700 dark:text-gray-300 mb-2" for="email">Email</label> <input type="email" id="email" class="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600 dark:text-white"> </div> <div class="mb-4"> <label class="block text-gray-700 dark:text-gray-300 mb-2" for="password">Password</label> <input type="password" id="password" class="w-full p-2 border rounded dark:bg-gray-700 dark:border-gray-600 dark:text-white"> </div> <button type="submit" class="w-full bg-indigo-600 text-white p-2 rounded hover:bg-indigo-700">Login</button> </form> </div> </div> <script src="/js/app.js"></script> </body> </html> </jitFile> <jitFile type="file" filePath="public/css/styles.css"> :root { --primary: #6366f1; --primary-dark: #4f46e5; }

.dark { --primary: #818cf8; --primary-dark: #6366f1; }

body { transition: background-color 0.3s, color 0.3s; }

.anime-card { transition: transform 0.2s; }

.anime-card:hover { transform: translateY(-5px); } </jitFile>

<jitFile type="file" filePath="public/js/app.js"> document.addEventListener('DOMContentLoaded', () => { // Theme toggle const themeToggle = document.getElementById('theme-toggle'); const html = document.documentElement;

themeToggle.addEventListener('click', () => { html.classList.toggle('dark'); localStorage.setItem('theme', html.classList.contains('dark') ? 'dark' : 'light'); });

// Check saved theme preference if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) { html.classList.add('dark'); }

// Login modal const loginBtn = document.getElementById('login-btn'); const loginModal = document.getElementById('login-modal'); const loginForm = document.getElementById('login-form');

loginBtn.addEventListener('click', () => { loginModal.classList.remove('hidden'); });

loginModal.addEventListener('click', (e) => { if (e.target === loginModal) { loginModal.classList.add('hidden'); } });

loginForm.addEventListener('submit', async (e) => { e.preventDefault(); const email = document.getElementById('email').value; const password = document.getElementById('password').value;

try {
  const response = await fetch('/api/users/login', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password })
  });

  if (!response.ok) throw new Error('Login failed');
  
  const data = await response.json();
  localStorage.setItem('token', data.token);
  loginModal.classList.add('hidden');
  loadAnimeList();
} catch (error) {
  alert(error.message);
}

});

// Load anime list async function loadAnimeList() { try { const token = localStorage.getItem('token'); if (!token) return;

  const response = await fetch('/api/anime', {
    headers: { 'Authorization': `Bearer ${token}` }
  });

  if (!response.ok) throw new Error('Failed to load anime');

  const animeList = await response.json();
  renderAnimeList(animeList);
} catch (error) {
  console.error(error);
}

}

function renderAnimeList(animeList) { const container = document.getElementById('anime-list'); container.innerHTML = '';

_
Updated files
v1
no give application like how app works and all so that i can tell u any changes required or not give directly after that we can see one by one

Anime & TV Series Tracker Application

Here's the complete application structure with all components working together:

anime-tracker/
├── server/
│   ├── config/
│   │   └── db.js
│   ├── controllers/
│   │   ├── animeController.js
│   │   ├── authController.js
│   │   └── clubController.js
│   ├── middleware/
│   │   ├── auth.js
│   │   └── error.js
│   ├── models/
│   │   ├── Anime.js
│   │   ├── Club.js
│   │   └── User.js
│   ├── routes/
│   │   ├── animeRoutes.js
│   │   ├── authRoutes.js
│   │   └── clubRoutes.js
│   └── server.js
├── client/
│   ├── public/
│   │   ├── css/
│   │   │   └── styles.css
│   │   ├── img/
│   │   ├── js/
│   │   │   └── app.js
│   │   └── index.html
│   ├── src/
│   │   ├── components/
│   │   │   ├── AnimeCard.js
│   │   │   ├── ClubCard.js
│   │   │   ├── Header.js
│   │   │   ├── LoginModal.js
│   │   │   └── Sidebar.js
│   │   ├── pages/
│   │   │   ├── AnimeDetail.js
│   │   │   ├── ClubDetail.js
│   │   │   ├── Dashboard.js
│   │   │   └── Login.js
│   │   ├── App.js
│   │   └── index.js
│   └── package.json
├── package.json
└── README.md

Key Features

  1. User Authentication
    • Registration with
i want to get anime shows from json file

Here's how we can modify the application to load anime shows from a JSON file:

This implementation:

  1. Stores anime data in a JSON file (anime-data.json)
  2. Loads the data when the server starts
  3. Provides API endpoints to access the data
  4. Displays the anime in a responsive grid layout
  5. Includes dark mode support
  6. Shows genre tags and basic information for each anime

You can now:

  1. Add more anime to the JSON file
  2. Modify the server to handle additional endpoints
  3. Customize the frontend display
  4. Add filtering/sorting functionality

Would you like me to add any specific features or make any adjustments to this setup?

Updated files
v2
see i need to get anime shows from data.json which provide data to mongodb

I'll help you create a solution to import anime data from a JSON file into MongoDB. Here's how we'll do it:

  1. First, let's create a data importer script
  2. Then we'll set up the data structure
  3. Finally, we'll create the import functionality

How to Use This Importer

  1. First, make sure you have:

    • Node.js installed
    • MongoDB running locally or a connection string to a remote MongoDB instance
    • The required packages installed (mongoose, dotenv)
  2. To import the data:

node importAnimeData.js --import
  1. To delete all anime data (optional):
node importAnimeData.js --delete
  1. The script will:
    • Connect to your MongoDB database
    • Read the anime data from data.json
    • Import all records into the Anime collection
    • Output success/error messages

You can modify the data.json file with your complete anime dataset. The importer will handle all the data insertion automatically.

Updated files
v3
i am so sorry but i'll provide u the frontend code why don't u give effective version of it so that i can later add backend

Got it! I'll provide a clean, modern frontend version of the Anime Tracker app that you can easily connect to your backend later. Here's the structure:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Anime Tracker</title>
  <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
  <style>
    .anime-card {
      transition: transform 0.3s ease, box-shadow 0.3s ease;
    }
    .anime-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 10px 20px rgba(0,0,0,0.1);
    }
    .progress-bar {
      height: 4px;
      background-color: #e2e8f0;
    }
    .progress-fill {
      height: 100%;
      background-color: #4f46e5;
      transition: width 0.5s ease;
    }
  </style>
</head>
<body class="bg-gray-50">
  <div id="app" class="min-h-screen">
    <!-- Navigation -->
    <nav class="bg-indigo-600 text-white shadow-lg">
      <div class="container mx-auto px-4 py-3 flex justify-between items-center">
        <div class="flex items-center space-x-2">
          <i class="fas fa-tv text-2xl"></i>
          <h1 class="text-xl font-bold">AnimeTracker</h1>
        </div>
        <div class="flex items-center space-x-4">
          <button class="p-2 rounded-full hover:bg-indigo-700 transition">
            <i class="fas fa-search"></i>
          </button>
          <button class="p-2 rounded-full hover:bg-indigo-700 transition">
            <i class="fas fa-user"></i>
          </button>
          <button id="theme-toggle" class="p-2 rounded-full hover:bg-indigo-700 transition">
            <i class="fas fa-moon"></i>
          </button>
        </div>
      </div>
    </nav>

    <!-- Main Content -->
    <main class="container mx-auto px-4 py-6">
      <div class="flex flex-col md:flex-row gap-6">
        <!-- Sidebar -->
        <aside class="w-full md:w-64 bg-white rounded-lg shadow-md p-4 h-fit">
          <h2 class="text-lg font-semibold mb-4">My List</h2>
          <ul class="space-y-2">
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50 text-indigo-600 font-medium">
                <i class="fas fa-list mr-2"></i> All Anime
              </a>
            </li>
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50">
                <i class="fas fa-play-circle mr-2"></i> Currently Watching
              </a>
            </li>
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50">
                <i class="fas fa-check-circle mr-2"></i> Completed
              </a>
            </li>
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50">
                <i class="fas fa-pause-circle mr-2"></i> On Hold
              </a>
            </li>
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50">
                <i class="fas fa-times-circle mr-2"></i> Dropped
              </a>
            </li>
            <li>
              <a href="#" class="flex items-center px-3 py-2 rounded hover:bg-indigo-50">
                <i class="fas fa-bookmark mr-2"></i> Plan to Watch
              </a>
            </li>
          </ul>

          <div class="mt-6">
            <h2 class="text-lg font-semibold mb-4">Genres</h2>
            <div class="flex flex-wrap gap-2">
              <span class="px-2 py-1 bg-gray-100 rounded-full text-sm">Action</span>
              <span class="px-2 py-1 bg-gray-100 rounded-full text-sm">Adventure</span>
              <span class="px-2 py-1 bg-gray-100 rounded-full text-sm">Comedy</span>
              <span class="px-2 py-1 bg-gray-100 rounded-full text-sm">Drama</span>
              <span class="px-2 py-1 bg-gray-100 rounded-full text-sm">Fantasy</span>
            </div>
          </div>
        </aside>

        <!-- Anime Grid -->
        <div class="flex-1">
          <div class="flex justify-between items-center mb-6">
            <h2 class="text-2xl font-bold">All Anime</h2>
            <div class="flex space-x-2">
              <button class="px-3 py-1 bg-indigo-600 text-white rounded hover:bg-indigo-700 transition">
                <i class="fas fa-plus mr-1"></i> Add Anime
              </button>
              <div class="relative">
                <select class="appearance-none bg-white border border-gray-300 rounded px-3 py-1 pr-8">
                  <option>Sort by</option>
                  <option>Recently Added</option>
                  <option>Title</option>
                  <option>Rating</option>
                </select>
                <i class="fas fa-chevron-down absolute right-2 top-2 text-gray-500"></i>
              </div>
            </div>
          </div>

          <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
            <!-- Anime Card 1 -->
            <div class="anime-card bg-white rounded-lg shadow-md overflow-hidden">
              <div class="relative">
                <img src="https://via.placeholder.com/300x450" alt="Anime Cover" class="w-full h-48 object-cover">
                <div class="absolute top-2 right-2 bg-indigo-600 text-white px-2 py-1 rounded-full text-xs font-semibold">
                  8.9
                </div>
              </div>
              <div class="p-4">
                <h3 class="font-bold text-lg mb-1">Attack on Titan</h3>
                <div class="flex items-center text-gray-500 text-sm mb-2">
                  <span>24 Episodes</span>
                  <span class="mx-2"></span>
                  <span>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Anime Tracker</title> <style> body { margin: 0; font-family: Arial, sans-serif; background-color: #1e1e2f; color: #ffffff; transition: background-color 0.3s, color 0.3s; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; min-height: 100vh; display: flex; flex-direction: column; overflow-x: hidden; } body.light-mode { background-color: #f0f0f0; color: #222222; } header { display: flex; justify-content: space-between; align-items: center; background-color: #282c34; padding: 0.75rem 1rem; user-select: none; } body.light-mode header { background-color: #ddd; color: #222; } .heading { font-size: 1.5rem; font-weight: bold; } nav.secondary-nav { display: flex; background-color: #282c34; padding: 0.5rem 1rem; gap: 1rem; user-select: none; } body.light-mode nav.secondary-nav { background-color: #ddd; color: #222; } button.nav-btn { background: none; border: none; color: inherit; font-size: 1rem; padding: 0.5rem 1rem; cursor: pointer; border-radius: 4px; position: relative; transition: background-color 0.3s; } button.nav-btn:hover, button.nav-btn:focus { background-color: #4a4e6d; outline: none; } body.light-mode button.nav-btn:hover, body.light-mode button.nav-btn:focus { background-color: #bbb; color: #222; } button.has-dropdown::after { content: " ▼"; font-size: 0.6rem; } .dropdown { position: absolute; background-color: #3d3f58; margin-top: 0.25rem; border-radius: 6px; box-shadow: 0 4px 8px rgba(0,0,0,0.3); min-width: 150px; display: none; flex-direction: column; z-index: 1000; } body.light-mode .dropdown { background-color: #e1e1e1; color: #222; box-shadow: 0 4px 8px rgba(0,0,0,0.15); } .dropdown button { background: none; border: none; color: inherit; padding: 0.5rem 1rem; text-align: left; width: 100%; cursor: pointer; } .dropdown button:hover, .dropdown button:focus { background-color: #5c5f7d; color: #fff; outline: none; } body.light-mode .dropdown button:hover, body.light-mode .dropdown button:focus { background-color: #ccc; color: #222; } .dropdown-container { position: relative; } @media (max-width: 600px) { header { flex-direction: column; align-items: flex-start; gap: 0.5rem; } nav.secondary-nav { flex-wrap: wrap; gap: 0.5rem; padding: 0.5rem; } button.nav-btn { flex: 1 1 auto; min-width: 100px; padding: 0.75rem 0.5rem; font-size: 1.1rem; } .dropdown { position: static; box-shadow: none; margin-top: 0; border-radius: 0 0 6px 6px; width: 100%; } } /* Main content area below nav */ main#main-content { flex-grow: 1; padding: 1rem; background-color: #222238; overflow-y: auto; user-select: none; } body.light-mode main#main-content { background-color: #fafafa; color: #222222; } /* Anime shows container */ #anime-shows { max-width: 800px; margin: 0 auto; display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; } .anime-card { background-color: #3d3f58; border-radius: 8px; width: 150px; padding: 0.75rem; box-shadow: 0 2px 8px rgba(0,0,0,0.5); cursor: default; user-select: none; transition: background-color 0.3s; display: flex; flex-direction: column; position: relative; } .anime-card:hover { background-color: #505379; } body.light-mode .anime-card { background-color: #e1e1e1; color: #222; } body.light-mode .anime-card:hover { background-color: #c1c1c5; } .anime-title { text-align: center; margin-bottom: 0.8rem; font-weight: bold; font-size: 1rem; } /* Review button */ .review-toggle-btn { background-color: #4a4e6d; border: none; color: white; padding: 0.5rem 0; cursor: pointer; border-radius: 4px; font-size: 0.95rem; user-select: none; transition: background-color 0.3s; width: 100%; } .review-toggle-btn:hover, .review-toggle-btn:focus { background-color: #6c70a1; outline: none; } body.light-mode .review-toggle-btn { background-color: #666; } body.light-mode .review-toggle-btn:hover, body.light-mode .review-toggle-btn:focus { background-color: #888; } /* Reviews list */ .reviews-list { margin-top: 0.6rem; font-size: 0.85rem; max-height: 110px; overflow-y: auto; } .review-message { background-color: #4a4e6d; border-radius: 5px; padding: 0.4rem 0.5rem; margin-bottom: 0.4rem; word-break: break-word; } body.light-mode .review-message { background-color: #ccc; color: #222; } /* Discussion panel */ #discussions-panel { display: none; height: 100%; max-width: 800px; margin: 0 auto; display: flex; flex-direction: column; } /* Discussion chat area */ #discussions-chat { flex-grow: 1; background-color: #3d3f58; border-radius: 6px; padding: 0.75rem; overflow-y: auto; margin-bottom: 1rem; color: white; font-size: 0.95rem; } body.light-mode #discussions-chat { background-color: #e1e1e1; color: #222; } .discussion-message { margin-bottom: 0.75rem; padding: 0.5rem; border-radius: 5px; background-color: #4a4e6d; word-wrap: break-word; } body.light-mode .discussion-message { background-color: #ccc; } /* Discussion form styling enhancements */ #discussion-form { display: flex; gap: 0.5rem; } #discussion-input { flex-grow: 1; padding: 0.5rem 0.75rem; border: none; border-radius: 6px; font-size: 1rem; background-color: #505379; color: #fff; transition: border-color 0.3s, background-color 0.3s; outline-offset: 2px; } body.light-mode #discussion-input { background-color: #fff; color: #222; border: 1px solid #ccc; } #discussion-input:focus { outline: none; border-color: #6c70a1; background-color: #626692; color: #fff; } body.light-mode #discussion-input:focus { background-color: #fff; color: #222; border-color: #888; } #discussion-submit { background-color: #4a4e6d; border: none; color: white; padding: 0 1.2rem; font-size: 1rem; border-radius: 6px; cursor: pointer; user-select: none; transition: background-color 0.3s; } #discussion-submit:hover, #discussion-submit:focus { background-color: #6c70a1; outline: none; } body.light-mode #discussion-submit { background-color: #666; } body.light-mode #discussion-submit:hover, body.light-mode #discussion-submit:focus { background-color: #888; } /* Modal overlay for review form */ .modal-overlay { position: fixed; top: 0; left: 0; right:0; bottom:0; background: rgba(0,0,0,0.6); display: none; justify-content: center; align-items: center; z-index: 2000; padding: 1rem; } .modal-overlay.show { display: flex; } .modal { background: #282c34; color: white; padding: 1.5rem; border-radius: 8px; max-width: 480px; width: 100%; box-shadow: 0 4px 12px rgba(0,0,0,0.7); position: relative; overflow-y: auto; max-height: 90vh; display: flex; flex-direction: column; user-select: none; } body.light-mode .modal { background: #e1e1e1; color: #222; } .modal h2 { margin-top: 0; margin-bottom: 1rem; } .modal button.close-btn { position: absolute; top: 0.3rem; right: 0.5rem; background: none; border: none; color: inherit; font-weight: bold; font-size: 1.5rem; cursor: pointer; } .modal button.close-btn:hover, .modal button.close-btn:focus { color: #999; outline: none; } /* Form styles inside modal */ .modal form label { display: block; margin-bottom: 0.4rem; font-weight: bold; user-select: none; } .modal form textarea { width: 100%; height: 80px; resize: none; padding: 0.5rem; border-radius: 5px; border: none; font-size: 1rem; background-color: #505379; color: white; box-sizing: border-box; transition: border-color 0.3s, background-color 0.3s; } body.light-mode .modal form textarea { background-color: #fff; color: #222; border: 1px solid #ccc; } .modal form textarea:focus { outline: none; border-color: #6c70a1; background-color: #626692; color: #fff; } body.light-mode .modal form textarea:focus { background-color: #fff; color: #222; border-color: #888; } .modal form select { width: 100%; padding: 0.4rem; border-radius: 5px; font-size: 1rem; border: none; background-color: #505379; color: white; margin-bottom: 1rem; box-sizing: border-box; transition: border-color 0.3s, background-color 0.3s; } body.light-mode .modal form select { background-color: #fff; color: #222; border: 1px solid #ccc; } .modal form select:focus { outline: none; border-color: #6c70a1; background-color: #626692; color: #fff; } body.light-mode .modal form select:focus { background-color: #fff; color: #222; border-color: #888; } .modal form button.submit-btn { background-color: #4a4e6d; border: none; color: white; padding: 0.6rem 1.2rem; cursor: pointer; border-radius: 5px; font-size: 1rem; user-select: none; transition: background-color 0.3s; width: 100%; box-sizing: border-box; } .modal form button.submit-btn:hover, .modal form button.submit-btn:focus { background-color: #6c70a1; outline: none; } body.light-mode .modal form button.submit-btn { background-color: #666; } body.light-mode .modal form button.submit-btn:hover, body.light-mode .modal form button.submit-btn:focus { background-color: #888; } /* For scroll inside modal form if needed */ .modal form { flex-grow: 1; } /* Responsive tweaks */ @media (max-width: 600px) { .anime-card { width: 100%; } } </style> </head> <body> <header> <div class="heading">Anime Tracker</div> <nav class="top-nav"> <div class="dropdown-container" id="settings-container"> <button class="nav-btn has-dropdown" id="settings-btn" aria-haspopup="true" aria-expanded="false" aria-controls="settings-dropdown">Settings</button> <div class="dropdown" id="settings-dropdown" role="menu" aria-labelledby="settings-btn"> <button type="button" class="dropdown-item" id="signup-btn">Signup</button> <button type="button" class="dropdown-item" id="login-btn">Login</button> <button type="button" class="dropdown-item" id="mode-btn">Mode</button> <button type="button" class="dropdown-item" id="logout-btn">Logout</button> </div> </div> </nav> </header> <nav class="secondary-nav" role="navigation" aria-label="Main navigation"> <div class="dropdown-container" id="all-container"> <button class="nav-btn has-dropdown" id="all-btn" aria-haspopup="true" aria-expanded="false" aria-controls="all-dropdown">All</button> <div class="dropdown" id="all-dropdown" role="menu" aria-labelledby="all-btn"> <button type="button" class="dropdown-item">Watching</button> <button type="button" class="dropdown-item">Completed</button> <button type="button" class="dropdown-item">Dropped</button> <button type="button" class="dropdown-item">Watchlist</button> </div> </div> <div class="dropdown-container" id="genre-container"> <button class="nav-btn has-dropdown" id="genre-btn" aria-haspopup="true" aria-expanded="false" aria-controls="genre-dropdown">Genre</button> <div class="dropdown" id="genre-dropdown" role="menu" aria-labelledby="genre-btn"> <button type="button" class="dropdown-item">Action</button> <button type="button" class="dropdown-item">Adventure</button> <button type="button" class="dropdown-item">Horror</button> <button type="button" class="dropdown-item">Romance</button> </div> </div> <div class="dropdown-container" id="clubs-container"> <button class="nav-btn has-dropdown" id="clubs-btn" aria-haspopup="true" aria-expanded="false" aria-controls="clubs-dropdown">Clubs</button> <div class="dropdown" id="clubs-dropdown" role="menu" aria-labelledby="clubs-btn"> <button type="button" class="dropdown-item" id="club-create-btn">Create Club</button> <button type="button" class="dropdown-item" id="club-join-btn">Join Club</button> <button type="button" class="dropdown-item" id="club-created-btn">Created Clubs</button> <button type="button" class="dropdown-item" id="club-joined-btn">Joined Clubs</button> </div> </div> <button class="nav-btn" id="discussions-btn" aria-pressed="false">Discussions</button> </nav> <main id="main-content" tabindex="-1"> <section id="anime-shows" aria-label="Anime shows list"> <!-- Anime card with Review button and reviews list --> <div class="anime-card" tabindex="0" data-anime="Attack on Titan"> <div class="anime-title">Attack on Titan</div> <button type="button" class="review-toggle-btn" aria-haspopup="dialog" aria-controls="review-modal" aria-label="Open review form for Attack on Titan">Review</button> <div class="reviews-list" aria-live="polite" aria-label="Reviews for Attack on Titan"></div> </div> <div class="anime-card" tabindex="0" data-anime="My Hero Academia"> <div class="anime-title">My Hero Academia</div> <button type="button" class="review-toggle-btn" aria-haspopup="dialog" aria-controls="review-modal" aria-label="Open review form for My Hero Academia">Review</button> <div class="reviews-list" aria-live="polite" aria-label="Reviews for My Hero Academia"></div> </div> <div class="anime-card" tabindex="0" data-anime="One Piece"> <div class="anime-title">One Piece</div> <button type="button" class="review-toggle-btn" aria-haspopup="dialog" aria-controls="review-modal" aria-label="Open review form for One Piece">Review</button> <div class="reviews-list" aria-live="polite" aria-label="Reviews for One Piece"></div> </div> <div class="anime-card" tabindex="0" data-anime="Demon Slayer"> <div class="anime-title">Demon Slayer</div> <button type="button" class="review-toggle-btn" aria-haspopup="dialog" aria-controls="review-modal" aria-label="Open review form for Demon Slayer">Review</button> <div class="reviews-list" aria-live="polite" aria-label="Reviews for Demon Slayer"></div> </div> <div class="anime-card" tabindex="0" data-anime="Naruto"> <div class="anime-title">Naruto</div> <button type="button" class="review-toggle-btn" aria-haspopup="dialog" aria-controls="review-modal" aria-label="Open review form for Naruto">Review</button> <div class="reviews-list" aria-live="polite" aria-label="Reviews for Naruto"></div> </div> </section> <section id="discussions-panel" aria-label="Discussions panel"> <div id="discussions-chat" aria-live="polite" aria-relevant="additions" role="log" tabindex="0" aria-atomic="false"> <!-- Discussion messages appear here --> </div> <form id="discussion-form" aria-label="Add new message"> <input type="text" id="discussion-input" name="discussion-input" aria-label="Type your message" placeholder="Type your message..." required autocomplete="off" /> <button type="submit" id="discussion-submit">Send</button> </form> </section> </main> <!-- Signup Modal --> <div class="modal-overlay" id="signup-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="signup-title"> <div class="modal"> <button class="close-btn" aria-label="Close Signup Modal" id="close-signup">&times;</button> <h2 id="signup-title">Signup</h2> <form id="signup-form"> <label for="signup-username">Username</label> <input type="text" id="signup-username" name="username" required autocomplete="username" /> <label for="signup-email">Email</label> <input type="email" id="signup-email" name="email" required autocomplete="email" /> <label for="signup-password">Password</label> <input type="password" id="signup-password" name="password" required autocomplete="new-password" /> <button type="submit" class="submit-btn">Sign Up</button> </form> </div> </div> <!-- Login Modal --> <div class="modal-overlay" id="login-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="login-title"> <div class="modal"> <button class="close-btn" aria-label="Close Login Modal" id="close-login">&times;</button> <h2 id="login-title">Login</h2> <form id="login-form"> <label for="login-username">Username or Email</label> <input type="text" id="login-username" name="username" required autocomplete="username" /> <label for="login-password">Password</label> <input type="password" id="login-password" name="password" required autocomplete="current-password" /> <button type="submit" class="submit-btn">Log In</button> </form> </div> </div> <!-- Clubs Modal --> <div class="modal-overlay" id="clubs-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="clubs-title"> <div class="modal" style="max-width: 480px;"> <button class="close-btn" aria-label="Close Clubs Modal" id="close-clubs-modal">&times;</button> <h2 id="clubs-title">Clubs</h2> <div class="club-content" id="club-content"> <!-- Dynamic content will be loaded here --> </div> </div> </div> <!-- REVIEW Modal --> <div class="modal-overlay" id="review-modal" aria-hidden="true" role="dialog" aria-modal="true" aria-labelledby="review-title"> <div class="modal" role="document"> <button class="close-btn" aria-label="Close Review Modal" id="close-review">&times;</button> <h2 id="review-title">Write a Review</h2> <form id="review-form" novalidate> <label for="review-textarea">Your Comment:</label> <textarea id="review-textarea" rows="4" placeholder="Write your comment here..." required></textarea> <label for="review-rating">Rating (out of 5):</label> <select id="review-rating" required> <option value="" disabled selected>Select rating</option> <option value="1">1 ★</option> <option value="2">2 ★★</option> <option value="3">3 ★★★</option> <option value="4">4 ★★★★</option> <option value="5">5 ★★★★★</option> </select> <button type="submit" class="submit-btn">Submit Review</button> </form> </div> </div> <script> // (JS code unchanged from previous response) // Dropdown toggles & modal handling is the same as before // Modes, modals, clubs, signup, login, discussions, review modal logic all same // I will paste the relevant JS code here for completeness: function toggleDropdown(btn, dropdown) { const isVisible = dropdown.style.display === 'flex'; closeAllDropdowns(); if (!isVisible) { dropdown.style.display = 'flex'; btn.setAttribute('aria-expanded', 'true'); } } function closeAllDropdowns() { document.querySelectorAll('.dropdown').forEach(dropdown => { dropdown.style.display = 'none'; }); document.querySelectorAll('.nav-btn.has-dropdown').forEach(btn => { btn.setAttribute('aria-expanded', 'false'); }); } function setupDropdown(containerId, btnId, dropdownId) { const container = document.getElementById(containerId); const btn = document.getElementById(btnId); const dropdown = document.getElementById(dropdownId); btn.addEventListener('click', (e) => { e.stopPropagation(); toggleDropdown(btn, dropdown); }); container.addEventListener('mouseleave', () => { closeAllDropdowns(); }); } setupDropdown('all-container', 'all-btn', 'all-dropdown'); setupDropdown('genre-container', 'genre-btn', 'genre-dropdown'); setupDropdown('settings-container', 'settings-btn', 'settings-dropdown'); setupDropdown('clubs-container', 'clubs-btn', 'clubs-dropdown'); document.addEventListener('click', () => { closeAllDropdowns(); }); const modeBtn = document.getElementById('mode-btn'); modeBtn.addEventListener('click', (e) => { e.stopPropagation(); const body = document.body; if (body.classList.contains('light-mode')) { body.classList.remove('light-mode'); localStorage.setItem('theme', 'dark'); } else { body.classList.add('light-mode'); localStorage.setItem('theme', 'light'); } closeAllDropdowns(); }); window.addEventListener('DOMContentLoaded', () => { const savedTheme = localStorage.getItem('theme'); if (savedTheme === 'light') { document.body.classList.add('light-mode'); } }); function openModal(modal) { modal.classList.add('show'); modal.setAttribute('aria-hidden', 'false'); document.body.style.overflow = 'hidden'; // prevent background scroll const focusable = modal.querySelector('button, input, textarea, select, [tabindex]:not([tabindex="-1"])'); if (focusable) focusable.focus(); } function closeModal(modal) { modal.classList.remove('show'); modal.setAttribute('aria-hidden', 'true'); document.body.style.overflow = ''; } const signupBtn = document.getElementById('signup-btn'); const signupModal = document.getElementById('signup-modal'); const closeSignup = document.getElementById('close-signup'); const signupForm = document.getElementById('signup-form'); signupBtn.addEventListener('click', e => { e.stopPropagation(); closeAllDropdowns(); openModal(signupModal); }); closeSignup.addEventListener('click', () => closeModal(signupModal)); signupModal.addEventListener('click', (e) => { if (e.target === signupModal) closeModal(signupModal); }); signupForm.addEventListener('submit', e => { e.preventDefault(); alert('Signup submitted! Username: ' + signupForm.username.value); closeModal(signupModal); signupForm.reset(); }); const loginBtn = document.getElementById('login-btn'); const loginModal = document.getElementById('login-modal'); const closeLogin = document.getElementById('close-login'); const loginForm = document.getElementById('login-form'); loginBtn.addEventListener('click', e => { e.stopPropagation(); closeAllDropdowns(); openModal(loginModal); }); closeLogin.addEventListener('click', () => closeModal(loginModal)); loginModal.addEventListener('click', (e) => { if (e.target === loginModal) closeModal(loginModal); }); loginForm.addEventListener('submit', e => { e.preventDefault(); alert('Login submitted! Username: ' + loginForm.username.value); closeModal(loginModal); loginForm.reset(); }); const clubsBtn = document.getElementById('clubs-btn'); const clubsModal = document.getElementById('clubs-modal'); const closeClubsModal = document.getElementById('close-clubs-modal'); const clubsDropdown = document.getElementById('clubs-dropdown'); const clubContent = document.getElementById('club-content'); clubsBtn.addEventListener('click', e => { e.stopPropagation(); closeAllDropdowns(); toggleDropdown(clubsBtn, clubsDropdown); }); closeClubsModal.addEventListener('click', () => closeModal(clubsModal)); clubsModal.addEventListener('click', (e) => { if (e.target === clubsModal) closeModal(clubsModal); }); const createBtn = document.getElementById('club-create-btn'); const joinBtn = document.getElementById('club-join-btn'); const createdBtn = document.getElementById('club-created-btn'); const joinedBtn = document.getElementById('club-joined-btn'); createBtn.addEventListener('click', () => { closeAllDropdowns(); clubContent.innerHTML = ` <h3>Create Club</h3> <form id="create-club-form"> <label for="club-name">Club Name</label> <input type="text" id="club-name" name="club-name" required /> <button type="submit" class="submit-btn">Create</button> </form> `; openModal(clubsModal); const createClubForm = document.getElementById('create-club-form'); createClubForm.addEventListener('submit', e => { e.preventDefault(); alert('Club created with name: ' + createClubForm['club-name'].value); closeModal(clubsModal); createClubForm.reset(); }); }); joinBtn.addEventListener('click', () => { closeAllDropdowns(); clubContent.innerHTML = ` <h3>Join Club</h3> <form id="join-club-form"> <label for="club-code">Club Code</label> <input type="text" id="club-code" name="club-code" required /> <button type="submit" class="submit-btn">Join</button> </form> `; openModal(clubsModal); const joinClubForm = document.getElementById('join-club-form'); joinClubForm.addEventListener('submit', e => { e.preventDefault(); alert('Requested join for club code: ' + joinClubForm['club-code'].value); closeModal(clubsModal); joinClubForm.reset(); }); }); createdBtn.addEventListener('click', () => { closeAllDropdowns(); clubContent.innerHTML = ` <h3>Created Clubs</h3> <ul> <li>My Anime Club</li> <li>Shonen Fans</li> </ul> `; openModal(clubsModal); }); joinedBtn.addEventListener('click', () => { closeAllDropdowns(); clubContent.innerHTML = ` <h3>Joined Clubs</h3> <ul> <li>Mystery Anime Lovers</li> <li>Romance Enthusiasts</li> </ul> `; openModal(clubsModal); }); const discussionsBtn = document.getElementById('discussions-btn'); const animeShowsSection = document.getElementById('anime-shows'); const discussionsPanel = document.getElementById('discussions-panel'); const mainContent = document.getElementById('main-content'); const discussionsChat = document.getElementById('discussions-chat'); const discussionForm = document.getElementById('discussion-form'); const discussionInput = document.getElementById('discussion-input'); const messages = []; function appendMessage(text) { const msgDiv = document.createElement('div'); msgDiv.classList.add('discussion-message'); msgDiv.textContent = text; discussionsChat.appendChild(msgDiv); scrollChatToBottom(); } function scrollChatToBottom() { discussionsChat.scrollTop = discussionsChat.scrollHeight; } discussionsBtn.addEventListener('click', () => { discussionsBtn.setAttribute('aria-pressed', 'true'); discussionsPanel.style.display = 'flex'; animeShowsSection.style.display = 'none'; mainContent.focus(); }); function showAnimeShows() { discussionsBtn.setAttribute('aria-pressed', 'false'); discussionsPanel.style.display = 'none'; animeShowsSection.style.display = 'flex'; mainContent.focus(); } document.getElementById('all-btn').addEventListener('click', () => { showAnimeShows(); }); document.getElementById('genre-btn').addEventListener('click', () => { showAnimeShows(); }); discussionForm.addEventListener('submit', e => { e.preventDefault(); const trimmed = discussionInput.value.trim(); if(trimmed.length === 0) return; messages.push(trimmed); appendMessage(trimmed); discussionInput.value = ''; discussionInput.focus(); }); document.addEventListener('keydown', e => { if(e.key === "Escape" || e.key === "Esc"){ if (signupModal.classList.contains('show')) closeModal(signupModal); else if (loginModal.classList.contains('show')) closeModal(loginModal); else if (clubsModal.classList.contains('show')) closeModal(clubsModal); else if (reviewModal.classList.contains('show')) closeModal(reviewModal); } }); const reviewModal = document.getElementById('review-modal'); const closeReviewBtn = document.getElementById('close-review'); const reviewForm = document.getElementById('review-form'); const reviewTextarea = document.getElementById('review-textarea'); const reviewRating = document.getElementById('review-rating'); const reviewTitle = document.getElementById('review-title'); let currentAnimeCard = null; document.querySelectorAll('.review-toggle-btn').forEach(btn => { btn.addEventListener('click', () => { const animeCard = btn.closest('.anime-card'); currentAnimeCard = animeCard; const animeTitle = animeCard.querySelector('.anime-title').textContent; reviewTitle.textContent = 'Write a Review for ' + animeTitle; reviewTextarea.value = ''; reviewRating.value = ''; openModal(reviewModal); }); }); closeReviewBtn.addEventListener('click', () => { closeModal(reviewModal); }); reviewModal.addEventListener('click', (e) => { if(e.target === reviewModal) { closeModal(reviewModal); } }); reviewForm.addEventListener('submit', e => { e.preventDefault(); const comment = reviewTextarea.value.trim(); const rating = reviewRating.value; if(comment === '' || rating === '') return alert('Please fill in both comment and rating.'); const reviewMessage = document.createElement('div'); reviewMessage.classList.add('review-message'); const stars = '★'.repeat(rating) + '☆'.repeat(5 - rating); reviewMessage.textContent = `${stars} - ${comment}`; if(currentAnimeCard){ const reviewsList = currentAnimeCard.querySelector('.reviews-list'); reviewsList.appendChild(reviewMessage); reviewsList.scrollTop = reviewsList.scrollHeight; } closeModal(reviewModal); }); </script> </body> </html> give effective revised version of it
<!-- Discussion Modal --> <div id="discussion-modal" class="modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50"> <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] flex flex-col"> <div class="p-4 border-b dark:border-gray-700"> <div class="flex justify-between continue this

Here's a more effective, modern version of your Anime Tracker frontend with improved structure and functionality:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Anime Tracker</title>
  <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    .anime-card {
      transition: all 0.3s ease;
    }
    .anime-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
    }
    .progress-fill {
      transition: width 0.5s ease;
    }
    .dark .discussion-message {
      background-color: #3d3f58;
    }
    .discussion-message {
      transition: all 0.3s ease;
    }
  </style>
</head>
<body class="bg-gray-50 dark:bg-gray-900 transition-colors duration-300">
  <div id="app" class="min-h-screen flex flex-col">
    <!-- Navigation -->
    <header class="bg-indigo-600 dark:bg-indigo-800 text-white shadow-lg">
      <div class="container mx-auto px-4 py-3 flex justify-between items-center">
        <div class="flex items-center space-x-3">
          <i class="fas fa-tv text-2xl"></i>
          <h1 class="text-xl font-bold">AnimeTracker</h1>
        </div>
        <div class="flex items-center space-x-4">
          <button id="search-btn" class="p-2 rounded-full hover:bg-indigo-700 dark:hover:bg-indigo-900 transition">
            <i class="fas fa-search"></i>
          </button>
          <button id="user-menu-btn" class="p-2 rounded-full hover:bg-indigo-700 dark:hover:bg-indigo-900 transition">
            <i class="fas fa-user"></i>
          </button>
          <button id="theme-toggle" class="p-2 rounded-full hover:bg-indigo-700 dark:hover:bg-indigo-900 transition">
            <i class="fas fa-moon dark:hidden"></i>
            <i class="fas fa-sun hidden dark:block"></i>
          </button>
        </div>
      </div>
    </header>

    <!-- Main Content -->
    <main class="flex-1 container mx-auto px-4 py-6">
      <div class="flex flex-col md:flex-row gap-6">
        <!-- Sidebar -->
        <aside class="w-full md:w-64 bg-white dark:bg-gray-800 rounded-lg shadow-md p-4 h-fit transition-colors duration-300">
          <h2 class="text-lg font-semibold mb-4 dark:text-white">My List</h2>
          <ul class="space-y-2">
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 text-indigo-600 dark:text-indigo-400 font-medium transition-colors duration-300">
                <i class="fas fa-list mr-2"></i> All Anime
              </button>
            </li>
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 dark:text-gray-300 transition-colors duration-300">
                <i class="fas fa-play-circle mr-2"></i> Watching
              </button>
            </li>
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 dark:text-gray-300 transition-colors duration-300">
                <i class="fas fa-check-circle mr-2"></i> Completed
              </button>
            </li>
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 dark:text-gray-300 transition-colors duration-300">
                <i class="fas fa-pause-circle mr-2"></i> On Hold
              </button>
            </li>
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 dark:text-gray-300 transition-colors duration-300">
                <i class="fas fa-times-circle mr-2"></i> Dropped
              </button>
            </li>
            <li>
              <button class="w-full text-left flex items-center px-3 py-2 rounded hover:bg-indigo-50 dark:hover:bg-gray-700 dark:text-gray-300 transition-colors duration-300">
                <i class="fas fa-bookmark mr-2"></i> Plan to Watch
              </button>
            </li>
          </ul>

          <div class="mt-6">
            <h2 class="text-lg font-semibold mb-4 dark:text-white">Genres</h2>
            <div class="flex flex-wrap gap-2">
              <button class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-300">
                Action
              </button>
              <button class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-300">
                Adventure
              </button>
              <button class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-300">
                Comedy
              </button>
              <button class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-300">
                Drama
              </button>
              <button class="px-3 py-1 bg-gray-100 dark:bg-gray-700 rounded-full text-sm hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-300">
                Fantasy
              </button>
            </div>
          </div>
        </aside>

        <!-- Content Area -->
        <div class="flex-1">
          <div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6 gap-4">
            <h2 class="text-2xl font-bold dark:text-white">All Anime</h2>
            <div class="flex flex-wrap gap-2">
              <button id="add-anime-btn" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-700 dark:hover:bg-indigo-800 text-white rounded transition-colors duration-300">
                <i class="fas fa-plus mr-1"></i> Add Anime
              </button>
              <div class="relative">
                <select class="appearance-none bg-white dark:bg-gray-700 dark:text-white border border-gray-300 dark:border-gray-600 rounded px-3 py-2 pr-8 focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors duration-300">
                  <option>Recently Added</option>
                  <option>Title (A-Z)</option>
                  <option>Rating (High-Low)</option>
                </select>
                <i class="fas fa-chevron-down absolute right-3 top-3 text-gray-500 dark:text-gray-400 pointer-events-none"></i>
              </div>
            </div>
          </div>

          <!-- Anime Grid -->
          <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
            <!-- Anime Card Template -->
            <div class="anime-card bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden transition-colors duration-300">
              <div class="relative">
                <img src="https://via.placeholder.com/300x450" alt="Anime Cover" class="w-full h-48 object-cover">
                <div class="absolute top-2 right-2 bg-indigo-600 text-white px-2 py-1 rounded-full text-xs font-semibold">
                  8.9
                </div>
                <div class="absolute bottom-0 left-0 right-0 bg-gray-900 bg-opacity-50 text-white p-2">
                  <div class="flex justify-between items-center text-xs">
                    <span>12/24 episodes</span>
                    <button class="p-1 rounded-full hover:bg-white hover:bg-opacity-20">
                      <i class="fas fa-ellipsis-h"></i>
                    </button>
                  </div>
                  <div class="w-full bg-gray-700 rounded-full h-1.5 mt-1">
                    <div class="bg-indigo-500 h-1.5 rounded-full progress-fill" style="width: 50%"></div>
                  </div>
                </div>
              </div>
              <div class="p-4">
                <h3 class="font-bold text-lg mb-1 dark:text-white">Attack on Titan</h3>
                <p class="text-gray-600 dark:text-gray-300 text-sm mb-3 line-clamp-2">
                  After his hometown is destroyed and his mother is killed, young Eren Jaeger vows to cleanse the earth of the giant humanoid Titans.
                </p>
                <div class="flex justify-between items-center">
                  <span class="text-sm text-gray-500 dark:text-gray-400">Action, Drama</span>
                  <button class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-800 dark:hover:text-indigo-300 transition-colors duration-300">
                    <i class="fas fa-chevron-right"></i>
                  </button>
                </div>
              </div>
            </div>

            <!-- More anime cards would go here -->
          </div>
        </div>
      </div>
    </main>

    <!-- Modals -->
    <!-- Add Anime Modal -->
    <div id="add-anime-modal" class="modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full max-h-[90vh] overflow-y-auto transition-colors duration-300">
        <div class="p-4 border-b dark:border-gray-700 flex justify-between items-center">
          <h3 class="text-lg font-semibold dark:text-white">Add New Anime</h3>
          <button id="close-add-anime" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="p-4">
          <form id="add-anime-form" class="space-y-4">
            <div>
              <label for="anime-title" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Title</label>
              <input type="text" id="anime-title" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors duration-300" required>
            </div>
            <div>
              <label for="anime-description" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Description</label>
              <textarea id="anime-description" rows="3" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors duration-300"></textarea>
            </div>
            <div>
              <label for="anime-episodes" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Total Episodes</label>
              <input type="number" id="anime-episodes" min="1" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors duration-300" required>
            </div>
            <div class="flex justify-end space-x-3 pt-2">
              <button type="button" id="cancel-add-anime" class="px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-300">
                Cancel
              </button>
              <button type="submit" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-700 dark:hover:bg-indigo-800 text-white rounded-md transition-colors duration-300">
                Add Anime
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- Discussion Modal -->
    <div id="discussion-modal" class="modal fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50 hidden">
      <div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] flex flex-col transition-colors duration-300">
        <div class="p-4 border-b dark:border-gray-700 flex justify-between items-center">
          <h3 class="text-lg font-semibold dark:text-white">Discussion: Attack on Titan</h3>
          <button id="close-discussion" class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300">
            <i class="fas fa-times"></i>
          </button>
        </div>
        <div class="flex-1 overflow-y-auto p-4 space-y-4">
          <!-- Discussion messages would go here -->
        </div>
        <div class="p-4 border-t dark:border-gray-700">
          <form id="discussion-form" class="flex gap-2">
            <input type="text" id="discussion-input" placeholder="Type your message..." class="flex-1 px-3 py-2 border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors duration-300">
            <button type="submit" class="px-4 py-2 bg-indigo-600 hover:bg-indigo-700 dark:bg-indigo-700 dark:hover:bg-indigo-800 text-white rounded-md transition-colors duration-300">
              Send
            </button>
          </form>
        </div>
      </div>
    </div>
  </div>

  <script>
    // Theme Toggle
    const themeToggle = document.getElementById('theme-toggle');
    const html = document.documentElement;
    
    // Check for saved theme preference or use system preference
    if (localStorage.getItem('theme') === 'dark' || 
        (!localStorage.getItem('theme') && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
      html.classList.add('dark');
    }

    themeToggle.addEventListener('click', () => {
      html.classList.toggle('dark');
      localStorage.setItem('theme', html.classList.contains('dark') ? 'dark' : 'light');
    });

    // Add Anime Modal
    const addAnimeBtn = document.getElementById('add-anime-btn');
    const addAnimeModal = document.getElementById('add-anime-modal');
    const closeAddAnime = document.getElementById('close-add-anime');
    const cancelAddAnime = document.getElementById('cancel-add-anime');
    const addAnimeForm = document.getElementById('add-anime-form');

    addAnimeBtn.addEventListener('click', () => {
      addAnimeModal.classList.remove('hidden');
    });

    closeAddAnime.addEventListener('click', () => {
      addAnimeModal.classList.add('hidden');
    });

    cancelAddAnime.addEventListener('click', () => {
      addAnimeModal.classList.add('hidden');
    });

    addAnimeForm.addEventListener('submit', (e) => {
      e.preventDefault();
      // Handle form submission
      addAnimeModal.classList.add('hidden');
      addAnimeForm.reset();
    });

    // Discussion Modal
    const discussionModal = document.getElementById('discussion-modal');
    const closeDiscussion = document.getElementById('close-discussion');
    const discussionForm = document.getElementById('discussion-form');
    const discussionInput = document.getElementById('discussion-input');

    // This would be triggered when clicking on a discussion button
    function openDiscussion() {
      discussionModal.classList.remove('hidden');
    }

    closeDiscussion.addEventListener('click', () => {
      discussionModal.classList.add('hidden');
    });

    discussionForm.addEventListener('submit', (e) => {
      e.preventDefault();
      const message = discussionInput.value.trim();
      if (message) {
        // Add message to discussion
        discussionInput.value = '';
      }
    });

    // Close modals when clicking outside
    document.addEventListener('click', (e) => {
      if (e.target.classList.contains('modal')) {
        e.target.classList.add('hidden');
      }
    });

    // Close modals with Escape key
    document.addEventListener('keydown', (e) => {
      if (e.key === 'Escape') {
        addAnimeModal.classList.add('hidden');
        discussionModal.classList.add('hidden');
      }
    });
  </script>
</body>
</html>

Key Improvements:

  1. Modern UI with Tailwind CSS:

    • Clean, responsive design with dark mode support
    • Better spacing and visual hierarchy
    • Smooth transitions and hover effects
  2. **Enhanced **