0% found this document useful (0 votes)
13 views9 pages

Project Documentation

CineMuse is a React-based web application that enables users to search and discover movies using the OMDB API, featuring a responsive design and intuitive interface. The application includes functionalities such as real-time movie search, detailed information display, and error handling. The technology stack consists of React 18, TypeScript, Vite, Tailwind CSS, and React Query for state management and data fetching.

Uploaded by

bhagwatsunny9290
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views9 pages

Project Documentation

CineMuse is a React-based web application that enables users to search and discover movies using the OMDB API, featuring a responsive design and intuitive interface. The application includes functionalities such as real-time movie search, detailed information display, and error handling. The technology stack consists of React 18, TypeScript, Vite, Tailwind CSS, and React Query for state management and data fetching.

Uploaded by

bhagwatsunny9290
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

# CineMuse Movie Web Application - Project Documentation

## Table of Contents
1. [Project Overview](#project-overview)
2. [Technology Stack](#technology-stack)
3. [Project Structure](#project-structure)
4. [Key Components](#key-components)
5. [Code Samples](#code-samples)
6. [Setup and Installation](#setup-and-installation)
7. [Deployment](#deployment)

## Project Overview

CineMuse is a modern React-based web application that allows users to search and
discover movies using the OMDB API. The application features a responsive design
with a cinema-themed UI, providing an intuitive interface for movie exploration.

### Key Features


- Movie search functionality with real-time results
- Responsive grid layout for movie display
- Detailed movie information
- Error handling and user feedback
- Mobile-friendly design

## Technology Stack

- **Frontend Framework**: React 18 with TypeScript


- **Build Tool**: Vite
- **Styling**: Tailwind CSS
- **UI Components**: shadcn/ui with Radix UI
- **State Management**: React Hooks and Context
- **Data Fetching**: Fetch API with React Query
- **Routing**: React Router DOM

## Project Structure

```
src/
├── components/
│ ├── ui/ # Reusable UI components
│ ├── [Link] # Movie display component
│ ├── [Link] # Grid layout for movies
│ └── [Link] # Search input component
├── hooks/
│ └── [Link] # Custom hook for movie data
├── lib/
│ └── [Link] # Utility functions
├── pages/
│ ├── [Link] # Main page
│ ├── [Link] # Movie detail page
│ └── [Link] # 404 page
├── [Link] # Main application component
└── [Link] # Entry point
```

## Key Components

### 1. Main Application Component ([Link])


The main application component sets up routing, providers, and lazy loading.
### 2. Index Page ([Link])
The main page that includes the search functionality and movie grid display.

### 3. Movie Card Component ([Link])


A reusable component that displays individual movie information.

### 4. Movie Search Component ([Link])


The search input component with debounced search functionality.

### 5. useMovies Hook ([Link])


A custom hook that handles movie data fetching from the OMDB API.

## Code Samples

### 1. Main Application Component (src/[Link])

```tsx
import { Suspense, lazy } from "react";
import { Toaster } from "@/components/ui/toaster";
import { Toaster as Sonner } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Index from "./pages/Index";
import MovieDetail from "./pages/MovieDetail";

// Lazy load non-critical pages


const NotFound = lazy(() => import("./pages/NotFound"));

const queryClient = new QueryClient();

const App = () => (


<QueryClientProvider client={queryClient}>
<TooltipProvider>
<Toaster />
<Sonner />
<BrowserRouter>
<Routes>
<Route path="/" element={<Index />} />
<Route path="/movie/:id" element={<MovieDetail />} />
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
<Route path="*" element={
<Suspense fallback={<div className="min-h-screen bg-background flex
items-center justify-center">
<div className="text-center">
<div className="w-8 h-8 border-4 border-primary border-t-
transparent rounded-full animate-spin mx-auto mb-4"></div>
<p className="text-muted-foreground">Loading...</p>
</div>
</div>}>
<NotFound />
</Suspense>
} />
</Routes>
</BrowserRouter>
</TooltipProvider>
</QueryClientProvider>
);
export default App;
```

### 2. Main Page Component (src/pages/[Link])

```tsx
import { useState } from "react";
import MovieSearch from "@/components/MovieSearch";
import MovieGrid from "@/components/MovieGrid";
import { useMovies } from "@/hooks/useMovies";
import { Film, Sparkles } from "lucide-react";

const Index = () => {


const { movies, isLoading, searchMovies } = useMovies();
const [hasSearched, setHasSearched] = useState(false);

const handleSearch = (query: string) => {


setHasSearched(true);
searchMovies(query);
};

return (
<div className="min-h-screen bg-background">
{/* Hero Section */}
<div className="relative overflow-hidden">
<div className="absolute inset-0 bg-cinema-gradient opacity-20" />
<div className="relative container mx-auto safe-area-padding px-4 py-12
sm:py-16 md:py-20">
<div className="text-center mb-12 sm:mb-16">
<div className="flex items-center justify-center gap-2 sm:gap-3 mb-4
sm:mb-6">
<Film className="w-8 h-8 sm:w-10 sm:h-10 md:w-12 md:h-12 text-primary
flex-shrink-0" />
<h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-7xl font-bold
bg-gradient-to-r from-primary via-primary to-accent bg-clip-text text-transparent">
CineMuse
</h1>
<Sparkles className="w-6 h-6 sm:w-7 sm:h-7 md:w-8 md:h-8 text-accent
flex-shrink-0" />
</div>
<p className="text-base sm:text-lg md:text-xl lg:text-2xl text-muted-
foreground mb-6 sm:mb-8 max-w-3xl mx-auto px-2">
Discover your next favorite movie, series, or episode with our
powerful search engine
</p>
<MovieSearch onSearch={handleSearch} isLoading={isLoading} />
</div>
</div>
</div>

{/* Results Section */}


<div className="container mx-auto safe-area-padding px-4 pb-16 sm:pb-20">
{hasSearched && (
<div className="mb-6 sm:mb-8">
<h2 className="text-2xl sm:text-3xl font-bold text-foreground mb-2">
Search Results
</h2>
<div className="w-16 sm:w-20 h-1 bg-primary rounded-full" />
</div>
)}

<MovieGrid
movies={movies}
isLoading={isLoading}
onMovieClick={(id) => {
[Link] = `/movie/${id}`;
}}
/>

{!hasSearched && !isLoading && (


<div className="text-center py-12 sm:py-16 md:py-20">
<div className="text-6xl sm:text-7xl md:text-8xl mb-6 sm:mb-8">🎭</div>
<h3 className="text-2xl sm:text-3xl font-bold text-foreground mb-3
sm:mb-4 px-4">
Welcome to CineMuse
</h3>
<p className="text-lg sm:text-xl text-muted-foreground mb-6 sm:mb-8
max-w-2xl mx-auto px-4">
Your ultimate destination for movie discovery. Search through
millions of movies,
TV series, and episodes to find your next entertainment obsession.
</p>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6
sm:gap-8 max-w-4xl mx-auto px-4">
<div className="text-center p-4 sm:p-6 bg-card/30 rounded-xl border
border-border/50 mobile-shadow">
<div className="text-3xl sm:text-4xl mb-3 sm:mb-4">🔍</div>
<h4 className="text-base sm:text-lg font-semibold text-foreground
mb-2">Smart Search</h4>
<p className="text-sm sm:text-base text-muted-foreground">Find
movies by title, year, or genre with our intelligent search</p>
</div>
<div className="text-center p-4 sm:p-6 bg-card/30 rounded-xl border
border-border/50 mobile-shadow">
<div className="text-3xl sm:text-4xl mb-3 sm:mb-4">⭐</div>
<h4 className="text-base sm:text-lg font-semibold text-foreground
mb-2">Detailed Info</h4>
<p className="text-sm sm:text-base text-muted-foreground">Get
comprehensive details including ratings and cast information</p>
</div>
<div className="text-center p-4 sm:p-6 bg-card/30 rounded-xl border
border-border/50 mobile-shadow sm:col-span-2 lg:col-span-1">
<div className="text-3xl sm:text-4xl mb-3 sm:mb-4">🎬</div>
<h4 className="text-base sm:text-lg font-semibold text-foreground
mb-2">All Formats</h4>
<p className="text-sm sm:text-base text-muted-foreground">Explore
movies, TV series, documentaries, and more</p>
</div>
</div>
</div>
)}
</div>
</div>
);
};

export default Index;


```

### 3. Movie Card Component (src/components/[Link])

```tsx
import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Star, Calendar } from "lucide-react";

interface MovieCardProps {
movie: {
imdbID: string;
Title: string;
Year: string;
Poster: string;
Type: string;
imdbRating?: string;
};
onClick?: (id: string) => void;
}

const MovieCard = ({ movie, onClick }: MovieCardProps) => {


const handleClick = () => {
if (onClick) {
onClick([Link]);
}
};

return (
<Card
className="group cursor-pointer transition-all duration-300 hover:shadow-
cinema bg-card-gradient border-border/50 sm:hover:scale-105 sm:hover:-translate-y-1
touch-target"
onClick={handleClick}
>
<CardContent className="p-0">
<div className="relative overflow-hidden rounded-lg">
<img
src={[Link] !== 'N/A' ? [Link] : '/[Link]'}
alt={[Link]}
className="w-full aspect-[2/3] object-cover transition-transform
duration-300 sm:group-hover:scale-110"
onError={(e) => {
[Link] = '/[Link]';
}}
/>
<div className="absolute inset-0 bg-gradient-to-t from-background/80 via-
transparent to-transparent opacity-0 sm:group-hover:opacity-100 transition-opacity
duration-300" />

{/* Mobile-friendly overlay - always visible on mobile */}


<div className="absolute bottom-0 left-0 right-0 p-2 sm:p-4 bg-gradient-
to-t from-background/90 to-transparent sm:transform sm:translate-y-full sm:group-
hover:translate-y-0 sm:transition-transform sm:duration-300">
<Badge variant="secondary" className="mb-1 sm:mb-2 text-xs
bg-primary/20 text-primary-foreground border-primary/30">
{[Link](0).toUpperCase() + [Link](1)}
</Badge>
<h3 className="font-bold text-foreground text-sm sm:text-lg mb-1 line-
clamp-2">
{[Link]}
</h3>
<div className="flex items-center gap-1 sm:gap-2 text-muted-
foreground">
<Calendar className="w-3 h-3 sm:w-4 sm:h-4 flex-shrink-0" />
<span className="text-xs sm:text-sm">{[Link]}</span>
{[Link] && (
<>
<Star className="w-3 h-3 sm:w-4 sm:h-4 ml-1 sm:ml-2 text-cinema-
gold flex-shrink-0" />
<span className="text-xs sm:text-sm text-cinema-
gold">{[Link]}</span>
</>
)}
</div>
</div>
</div>
</CardContent>
</Card>
);
};

export default MovieCard;


```

### 4. Custom Hook for Movie Data (src/hooks/[Link])

```tsx
import { useState } from "react";
import { useToast } from "@/hooks/use-toast";

interface Movie {
imdbID: string;
Title: string;
Year: string;
Poster: string;
Type: string;
}

interface MovieResponse {
Search: Movie[];
totalResults: string;
Response: string;
Error?: string;
}

export const useMovies = () => {


const [movies, setMovies] = useState<Movie[]>([]);
const [isLoading, setIsLoading] = useState(false);
const { toast } = useToast();

const searchMovies = async (query: string) => {


setIsLoading(true);

try {
// Using a demo API key - in production, this should be handled more securely
const API_KEY = 'd99019f'; // Updated API key
const response = await fetch(
`[Link]
{encodeURIComponent(query)}&type=movie`
);

const data: MovieResponse = await [Link]();

if ([Link] === "True" && [Link]) {


setMovies([Link]);
toast({
title: "Movies found!",
description: `Found ${[Link]} movies matching "${query}"`,
});
} else {
setMovies([]);
toast({
title: "No movies found",
description: [Link] || `No movies found for "${query}"`,
variant: "destructive",
});
}
} catch (error) {
[Link]("Error fetching movies:", error);
setMovies([]);
toast({
title: "Error",
description: "Failed to fetch movies. Please check your API key and try
again.",
variant: "destructive",
});
} finally {
setIsLoading(false);
}
};

return {
movies,
isLoading,
searchMovies,
};
};
```

### 5. UI Button Component (src/components/ui/[Link])

```tsx
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const buttonVariants = cva(


"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-
sm font-medium ring-offset-background transition-colors focus-visible:outline-none
focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none
[&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-
foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)

export interface ButtonProps


extends [Link]<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}

const Button = [Link]<HTMLButtonElement, ButtonProps>(


({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
[Link] = "Button"

export { Button, buttonVariants }


```

## Setup and Installation

### Prerequisites
- [Link] (version 18 or higher)
- npm or yarn package manager

### Installation Steps

1. Clone the repository:


```bash
git clone <YOUR_GIT_URL>
```

2. Navigate to the project directory:


```bash
cd vido-muse-react-43
```

3. Install dependencies:
```bash
npm install
```

4. Start the development server:


```bash
npm run dev
```

The application will be available at `[Link]

### Build for Production

To create a production build:


```bash
npm run build
```

To preview the production build:


```bash
npm run preview
```

## Deployment

This project can be deployed using Lovable platform:

1. Open [Lovable]([Link]
83655123491a)
2. Click on "Share" -> "Publish"

For custom domain configuration:


1. Navigate to Project > Settings > Domains
2. Click "Connect Domain"
3. Follow the instructions in the [Custom Domain
Guide]([Link]

---

*This documentation provides a comprehensive overview of the CineMuse movie web


application, including its architecture, key components, and implementation
details. All code samples are extracted directly from the project source files.*

You might also like