shreshth-mehra_Obsidian-TV-.../Components/headerView.jsx
Shreshth-mehra 6c965a539d v1.3
2024-06-20 23:27:34 -07:00

298 lines
9.9 KiB
JavaScript

// Header.jsx
import React, { useState } from 'react';
import { Box, IconButton, Drawer, Typography, Button, Grid, Container } from "@mui/material";
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import MenuIcon from '@mui/icons-material/Menu';
import MoviePropertiesFilter from './propertiesFilter';
import MovieRatingFilter from './ratingFilter';
import MovieGenreFilter from './genreFilter';
import SortFilter from './sortFilter';
import AddNew from './addNew';
import MovieTypeFilter from './typeFilter';
import MovieSelectPopUp from './movieSelectPopUp';
import { Platform, requestUrl, Notice } from "obsidian";
const Header = ({ showTrailerAndPosterLinks, movieProperties, handleClearAllFilters, selectedProperties, handlePropertyChange, selectedRating, handleRatingChange, genres, selectedGenres, handleGenreChange, selectedTypes, handleTypeChange, createMarkdownFile, handleSortChange, sortOption, sortOrder, toggleSortOrder, themeMode, plugin }) => {
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
const [addDialogOpen, setAddDialogOpen] = useState(false);
const [searchResults, setSearchResults] = useState([]);
const [selectionDialogOpen, setSelectionDialogOpen] = useState(false);
const [selectedMovieState, setSelectedMovieState] = useState([]);
const [errorOpen, setErrorOpen] = useState(false);
const handleErrorOpen = () => {
setErrorOpen(true);
};
const handleErrorClose = () => {
setErrorOpen(false);
};
const handleAddMovie = async (movieData) => {
setSelectedMovieState(movieData);
const searchType = movieData.type === 'Series' ? 'tv' : 'movie';
try {
const searchUrl = `https://api.themoviedb.org/3/search/${searchType}?api_key=${plugin.settings.apiKey}&query=${encodeURIComponent(movieData.name)}`;
const searchResponse = await requestUrl({
url: searchUrl,
method: 'GET',
});
const searchData = await searchResponse.json;
if (searchData.results && searchData.results.length > 0) {
setSearchResults(searchData.results.slice(0, plugin.settings.numberOfResults));
setSelectionDialogOpen(true); // Open the selection dialog
} else {
console.log(`No results found for ${movieData.type}:`, movieData.name);
}
} catch (error) {
console.error(`Error fetching ${movieData.type} details:`, error);
handleErrorOpen();
}
};
const handleMovieSelect = async (selectedItem) => {
setSelectionDialogOpen(false); // Close the dialog
setSearchResults([]); // Clear the search results
const isTvShow = selectedItem.first_air_date !== undefined;
const detailsType = isTvShow ? 'tv' : 'movie';
try {
// Fetch detailed movie information for the selected movie
const detailsUrl = `https://api.themoviedb.org/3/${detailsType}/${selectedItem.id}?api_key=${plugin.settings.apiKey}&append_to_response=videos`;
const detailsResponse = await requestUrl({
url: detailsUrl,
method: 'GET',
});
const detailsData = await detailsResponse.json;
const creditsUrl = `https://api.themoviedb.org/3/${detailsType}/${selectedItem.id}/credits?api_key=${plugin.settings.apiKey}`;
const creditsResponse = await requestUrl({
url: creditsUrl,
method: 'GET',
});
const creditsData = await creditsResponse.json;
const directors = creditsData.crew.filter(member => member.job === 'Director').map(director => director.name).join(', ');
const originalLanguage = detailsData.original_language;
const overview = detailsData.overview;
let productionCompanies = '';
if (detailsData.production_companies && detailsData.production_companies.length > 0) {
productionCompanies = detailsData.production_companies.slice(0, 2).map(company => company.name).join(', ');
}
let trailer = '';
if (detailsData.videos && detailsData.videos.results.length > 0) {
const trailerData = detailsData.videos.results.find(video => video.type === 'Trailer');
if (trailerData) {
trailer = `https://www.youtube.com/watch?v=${trailerData.key}`;
}
}
const posterLink = `https://image.tmdb.org/t/p/original${detailsData.poster_path}`;
let budget = null;
let revenue = null;
let belongsToCollection = null;
if (!isTvShow) {
budget = detailsData.budget;
revenue = detailsData.revenue;
belongsToCollection = detailsData.belongs_to_collection ? detailsData.belongs_to_collection.name : null;
}
const escapeDoubleQuotes = (str) => str.replace(/"/g, '\\"');
const movieYAML = `---
Title: "${detailsData.title || detailsData.name}"
Rating: ${selectedMovieState.rating}
Status: "${selectedMovieState.status}"
Type: "${selectedMovieState.type}"
Poster: "https://image.tmdb.org/t/p/original${detailsData.poster_path}"
Genre: "${detailsData.genres.map(genre => genre.name).join(', ')}"
${isTvShow ? `First Air Date: ${selectedItem.first_air_date}` : `Duration: ${detailsData.runtime} minutes`}
Avg vote: ${detailsData.vote_average}
Popularity: ${detailsData.popularity}
Cast: "${creditsData.cast.slice(0, 10).map(member => member.name).join(', ')}"
TMDB ID: ${selectedItem.id}
Director: "${directors}"
tags: "tvtracker, ${selectedMovieState.type}"
original_language: "${originalLanguage}"
overview: "${escapeDoubleQuotes(overview)}"
trailer: "${trailer}"
budget: ${budget}
revenue: ${revenue}
belongs_to_collection: ${belongsToCollection ? `"${belongsToCollection}"` : '""'}
production_company: "${productionCompanies}"
---`;
let content = movieYAML;
if (showTrailerAndPosterLinks) {
if (detailsData.poster_path) {
content += `\n![Poster](${posterLink})`;
}
if (trailer != '') {
content += `\n![Trailer](${trailer})`;
}
}
const title = detailsData.title || detailsData.name; // TV shows use 'name' instead of 'title'
const fileName = `${title.replace(/[\/\\:]/g, '_')}`; // Sanitize title for filename
await createMarkdownFile(fileName, content);
new Notice('Successfully added. Please restart plugin to view it in the library');
} catch (error) {
new Notice('Error: Could not add movie');
console.error('Error processing the selected movie:', error);
}
};
const handleOpenAddDialog = () => {
setAddDialogOpen(true);
};
const handleCloseAddDialog = () => {
setAddDialogOpen(false);
};
const handleDrawerToggle = () => {
setMobileFiltersOpen(!mobileFiltersOpen);
};
const filters = (
<>
<Box mb={2}> {/* Margin bottom */}
<SortFilter
sortOption={sortOption}
sortOrder={sortOrder}
onSortChange={handleSortChange}
toggleSortOrder={toggleSortOrder} />
</Box>
<Box mb={2}>
<MoviePropertiesFilter
movieProperties={movieProperties}
selectedProperties={selectedProperties}
handlePropertyChange={handlePropertyChange}
/>
</Box>
<Box mb={2}>
<MovieGenreFilter
genres={genres}
selectedGenres={selectedGenres}
handleGenreChange={handleGenreChange}
/>
</Box>
<Box mb={2}>
<MovieRatingFilter
selectedRating={selectedRating}
handleRatingChange={handleRatingChange}
/>
</Box>
<Box mb={2}>
<MovieTypeFilter
selectedTypes={selectedTypes}
handleTypeChange={handleTypeChange}
/>
</Box>
<Box mb={2}>
<Button variant="contained" onClick={handleClearAllFilters} style={{
color: 'inherit', maxWidth: '100px', height: 'auto',
whiteSpace: 'wrap',
overflow: 'hidden',
padding: '8px 8px',
fontSize: '10px'
}}>Clear All filters</Button>
</Box>
</>
);
return (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '8px 0', marginBottom: '16px' }}>
<Dialog open={errorOpen} onClose={handleErrorClose}>
<DialogTitle>{"Unauthorized Access"}</DialogTitle>
<DialogContent>
<DialogContentText>
Please check your API key or internet connection.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleErrorClose}>Close</Button>
</DialogActions>
</Dialog>
<Button sx={{
color: 'inherit', maxWidth: '120px', height: 'auto',
whiteSpace: 'wrap',
overflow: 'hidden',
padding: '8px 8px',
fontSize: '12px'
}} onClick={handleOpenAddDialog}>Add New</Button>
<AddNew
open={addDialogOpen}
handleClose={handleCloseAddDialog}
handleAddMovie={handleAddMovie}
themeMode={themeMode}
/>
{Platform.isMobile ? (
<>
<IconButton
color="inherit"
aria-label="open filters"
edge="end"
onClick={handleDrawerToggle}
>
<MenuIcon />
</IconButton>
<Drawer
anchor="top"
open={mobileFiltersOpen}
onClose={handleDrawerToggle}
sx={{
'& .MuiDrawer-paper': {
backgroundColor: themeMode === 'dark' ? '#121212' : '#3a3b3c', // Example dark color, you can choose any
color: 'white'
},
}}
>
<Container style={{ padding: '30px' }}>
{filters}
</Container>
</Drawer>
</>
) : (
<Box sx={{ display: 'flex', gap: '16px' }}>
{filters}
</Box>
)}
<MovieSelectPopUp movies={searchResults} onSelect={handleMovieSelect} onClose={() => setSelectionDialogOpen(false)} />
</Box>
);
};
export default Header;