Skip to content

Commit

Permalink
feat: search internal and external in log media
Browse files Browse the repository at this point in the history
  • Loading branch information
dinkelspiel committed May 5, 2024
1 parent 7d48f27 commit e594dc4
Show file tree
Hide file tree
Showing 13 changed files with 404 additions and 144 deletions.
2 changes: 1 addition & 1 deletion app/(app)/dashboard/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const Dashboard = ({
error: queryError,
isLoading: queryIsLoading,
} = useSwr<number[], { error: string }>(
`/api/user/entries/search?q=${filterTitle}`,
`/api/user/entries?q=${filterTitle}`,
fetcher
);

Expand Down
9 changes: 8 additions & 1 deletion app/(app)/dashboard/userEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,14 @@ const UserEntryComponent = ({

return (
<>
<UserEntryCard userEntry={userEntry} onClick={() => setOpen(true)} />
<UserEntryCard
title={userEntry.entry.originalTitle}
backgroundImage={userEntry.entry.posterPath}
category={userEntry.entry.category}
releaseDate={userEntry.entry.releaseDate}
rating={userEntry.rating}
onClick={() => setOpen(true)}
/>

{(() => {
if (isDesktop) {
Expand Down
14 changes: 12 additions & 2 deletions app/(app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import AddLog from '@/components/addLog';
import SidebarLayout from '@/components/layouts/sidebar';
import { Sidebar, SidebarButton } from '@/components/sidebar';
import { Sidebar, SidebarButton, SidebarFooter } from '@/components/sidebar';
import { Button } from '@/components/ui/button';
import UserDisplay from '@/components/userDisplay';
import { validateSessionToken } from '@/server/auth/validateSession';
import { Home, UsersRound } from 'lucide-react';
import { Home, Plus, UsersRound } from 'lucide-react';
import { redirect } from 'next/navigation';
import { ReactNode } from 'react';
import { Toaster } from 'sonner';
Expand All @@ -28,6 +30,14 @@ const Layout = async ({ children }: { children: ReactNode }) => {
<UsersRound className="size-3" />
Community
</SidebarButton>
<SidebarFooter>
<AddLog>
<Button>
<Plus />
Log Media
</Button>
</AddLog>
</SidebarFooter>
</Sidebar>

<main className="flex flex-col gap-4 px-5 py-4">{children}</main>
Expand Down
45 changes: 45 additions & 0 deletions app/api/entries/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { validateSessionToken } from '@/server/auth/validateSession';
import prisma from '@/server/db';
import { Category } from '@prisma/client';
import { NextRequest } from 'next/server';

export const GET = async (request: NextRequest) => {
const user = await validateSessionToken();

if (!user) {
return Response.json({ error: 'You are not logged in' }, { status: 400 });
}

const query = request.nextUrl.searchParams.get('q');
const take = request.nextUrl.searchParams.get('take')
? Number(request.nextUrl.searchParams.get('take'))
: undefined;
const categories = request.nextUrl.searchParams.get('categories')
? (request.nextUrl.searchParams.get('categories')!.split(',') as Category[])
: undefined;

return Response.json(
await prisma.entry.findMany({
where: {
category: categories
? {
in: categories.filter(e => !!e),
}
: undefined,
alternativeTitles: {
some: {
title: {
contains: query ?? '',
},
},
},
},
take,
orderBy: {
userEntries: {
_count: 'desc',
},
},
})
);
};
43 changes: 0 additions & 43 deletions app/api/import/book/search/route.ts

This file was deleted.

38 changes: 0 additions & 38 deletions app/api/import/movie/search/route.ts

This file was deleted.

112 changes: 112 additions & 0 deletions app/api/import/search/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import prisma from '@/server/db';
import { Category } from '@prisma/client';
import { NextRequest } from 'next/server';

export const dynamic = 'force-dynamic';

export const GET = async (request: NextRequest) => {
const search = request.nextUrl.searchParams.get('q');
const excludeExisting = !!Boolean(
request.nextUrl.searchParams.get('excludeExisting')
); // Exclude media already in the local database
const take = request.nextUrl.searchParams.get('take')
? Number(request.nextUrl.searchParams.get('take'))
: 10;
const categories = request.nextUrl.searchParams.get('categories')
? (request.nextUrl.searchParams.get('categories')!.split(',') as Category[])
: ['Book', 'Series', 'Movie'];

if (!search) {
return Response.json([]);
}

const openLibrary = (
await (
await fetch(
`https://openlibrary.org/search.json?title=${search.replace(' ', '+')}`
)
).json()
).docs
.map((ol: any) => {
let lowestReleaseDate = new Date();
let releaseDateFallback: string | undefined = undefined;

if (ol.publish_date) {
for (const d of ol.publish_date) {
const date = new Date(d);
if (date.getTime() < lowestReleaseDate.getTime()) {
lowestReleaseDate = date;
}
}
} else {
releaseDateFallback = 'No release date';
}

return {
title: ol.title,
category: 'Book',
releaseDate: releaseDateFallback ?? lowestReleaseDate.toDateString(),
author: ol.author_name ? ol.author_name[0] : '',
foreignId: ol.key.split('/')[ol.key.split('/').length - 1],
posterPath: `https://covers.openlibrary.org/b/olid/${ol.edition_key[0]}-L.jpg`,
};
})
.filter((e: any) => !!new Date(e.releaseDate))
.filter(() => categories.includes('Book'));

const options = {
method: 'GET',
headers: {
accept: 'application/json',
Authorization: `Bearer ${process.env.TMDB_ACCESS_TOKEN}`,
},
};

console.log('b');

const tmdb = (
await (
await fetch(
`https://api.themoviedb.org/3/search/multi?query=${search}&include_adult=false&language=en-US&page=1`,
options
)
).json()
).results
.map((tmdb: any) => ({
title: tmdb.original_title ?? tmdb.name,
category: tmdb.media_type === 'tv' ? 'Series' : 'Movie',
releaseDate:
tmdb.type === 'tv'
? new Date(tmdb.first_air_date).toDateString()
: new Date(tmdb.release_date).toDateString(),
author: '',
foreignId: tmdb.id,
posterPath: 'https://image.tmdb.org/t/p/original/' + tmdb.poster_path,
}))
.filter((tmdb: any) => categories?.includes(tmdb.category))
.filter((e: any) => e.releaseDate !== 'Invalid Date');

if (excludeExisting) {
let finalMedia = [];
for (const media of [...openLibrary, ...tmdb]) {
const existing = await prisma.entry.findFirst({
where: {
foreignId: media.foreignId.toString(),
category: media.category,
},
});

if (!existing) {
finalMedia.push(media);
}
}

console.log('c');

return Response.json(finalMedia.slice(0, take));
}

console.log('d');

return Response.json([...openLibrary, ...tmdb].slice(0, take));
};
38 changes: 0 additions & 38 deletions app/api/import/series/search/route.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ export const GET = async (request: NextRequest) => {

const query = request.nextUrl.searchParams.get('q');

if (!query) {
return Response.json({ error: 'No query provided' }, { status: 400 });
}

return Response.json(
(
await prisma.userEntry.findMany({
Expand All @@ -24,7 +20,7 @@ export const GET = async (request: NextRequest) => {
alternativeTitles: {
some: {
title: {
contains: query,
contains: query ?? '',
},
},
},
Expand Down
Loading

0 comments on commit e594dc4

Please sign in to comment.