generated from mzaien/remix-nextui-vercel
-
Notifications
You must be signed in to change notification settings - Fork 182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#106, #103: add similar, recommendations, cast, crew tab for detail page #123
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,56 @@ | ||
import { Text } from '@nextui-org/react'; | ||
|
||
const CastPage = () => ( | ||
<Text b h4 css={{ paddingLeft: '88px' }}> | ||
{' '} | ||
In development | ||
</Text> | ||
); | ||
/* eslint-disable @typescript-eslint/no-throw-literal */ | ||
import { LoaderFunction, json } from '@remix-run/node'; | ||
import { useLoaderData } from '@remix-run/react'; | ||
import { Row } from '@nextui-org/react'; | ||
import { getCredits } from '~/services/tmdb/tmdb.server'; | ||
import { ICast } from '~/services/tmdb/tmdb.types'; | ||
import PeopleList from '~/src/components/people/PeopleList'; | ||
|
||
type LoaderData = { | ||
cast: ICast[]; | ||
}; | ||
|
||
export const loader: LoaderFunction = async ({ params }) => { | ||
const { movieId } = params; | ||
const mid = Number(movieId); | ||
|
||
if (!mid) throw new Response('Not found', { status: 404 }); | ||
const credits = await getCredits('movie', mid); | ||
|
||
if (!credits) throw new Response('Not found', { status: 404 }); | ||
|
||
return json<LoaderData>({ cast: credits.cast }); | ||
}; | ||
|
||
const CastPage = () => { | ||
const { cast } = useLoaderData<LoaderData>(); | ||
|
||
return ( | ||
<Row | ||
fluid | ||
justify="center" | ||
align="center" | ||
css={{ | ||
flexDirection: 'column', | ||
'@xsMax': { | ||
paddingLeft: 'calc(var(--nextui-space-sm))', | ||
paddingRight: 'calc(var(--nextui-space-sm))', | ||
}, | ||
'@xs': { | ||
paddingLeft: '88px', | ||
paddingRight: '1rem', | ||
}, | ||
}} | ||
> | ||
{/* | ||
TODO: Need react virtual to load this list | ||
This list has a lot of items, so i limit it to 24 items until we install react virtual | ||
*/} | ||
{cast && cast.length > 0 && ( | ||
<PeopleList listType="grid" items={cast.slice(0, 24)} listName="Cast" /> | ||
)} | ||
</Row> | ||
); | ||
}; | ||
|
||
export default CastPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,56 @@ | ||
import { Text } from '@nextui-org/react'; | ||
|
||
const CrewPage = () => ( | ||
<Text b h4 css={{ paddingLeft: '88px' }}> | ||
{' '} | ||
In development | ||
</Text> | ||
); | ||
/* eslint-disable @typescript-eslint/no-throw-literal */ | ||
import { LoaderFunction, json } from '@remix-run/node'; | ||
import { useLoaderData } from '@remix-run/react'; | ||
import { Row } from '@nextui-org/react'; | ||
import { getCredits } from '~/services/tmdb/tmdb.server'; | ||
import { ICrew } from '~/services/tmdb/tmdb.types'; | ||
import PeopleList from '~/src/components/people/PeopleList'; | ||
|
||
type LoaderData = { | ||
crew: ICrew[]; | ||
}; | ||
|
||
export const loader: LoaderFunction = async ({ params }) => { | ||
const { movieId } = params; | ||
const mid = Number(movieId); | ||
|
||
if (!mid) throw new Response('Not found', { status: 404 }); | ||
const credits = await getCredits('movie', mid); | ||
|
||
if (!credits) throw new Response('Not found', { status: 404 }); | ||
|
||
return json<LoaderData>({ crew: credits.crew }); | ||
}; | ||
|
||
const CrewPage = () => { | ||
const { crew } = useLoaderData<LoaderData>(); | ||
|
||
return ( | ||
<Row | ||
fluid | ||
justify="center" | ||
align="center" | ||
css={{ | ||
flexDirection: 'column', | ||
'@xsMax': { | ||
paddingLeft: 'calc(var(--nextui-space-sm))', | ||
paddingRight: 'calc(var(--nextui-space-sm))', | ||
}, | ||
'@xs': { | ||
paddingLeft: '88px', | ||
paddingRight: '1rem', | ||
}, | ||
}} | ||
> | ||
{/* | ||
TODO: Need react virtual to load this list | ||
This list has a lot of items, so i limit it to 24 items until we install react virtual | ||
*/} | ||
{crew && crew.length > 0 && ( | ||
<PeopleList listType="grid" items={crew.slice(0, 24)} listName="Crew" /> | ||
)} | ||
</Row> | ||
); | ||
}; | ||
|
||
export default CrewPage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* eslint-disable @typescript-eslint/no-throw-literal */ | ||
import { LoaderFunction, json } from '@remix-run/node'; | ||
import { useLoaderData, useNavigate, Link, RouteMatch, useParams } from '@remix-run/react'; | ||
import { Row, Pagination } from '@nextui-org/react'; | ||
import { getRecommendation } from '~/services/tmdb/tmdb.server'; | ||
import MediaList from '~/src/components/Media/MediaList'; | ||
import useMediaQuery from '~/hooks/useMediaQuery'; | ||
import i18next from '~/i18n/i18next.server'; | ||
|
||
type LoaderData = { | ||
recommendations: Awaited<ReturnType<typeof getRecommendation>>; | ||
}; | ||
|
||
export const loader: LoaderFunction = async ({ request, params }) => { | ||
const { movieId } = params; | ||
const mid = Number(movieId); | ||
if (!mid) throw new Response('Not Found', { status: 404 }); | ||
|
||
const locale = await i18next.getLocale(request); | ||
const url = new URL(request.url); | ||
let page = Number(url.searchParams.get('page')) || undefined; | ||
if (page && (page < 1 || page > 1000)) page = 1; | ||
|
||
const recommendations = await getRecommendation('movie', mid, page, locale); | ||
if (!recommendations) throw new Response('Not Found', { status: 404 }); | ||
|
||
return json<LoaderData>({ | ||
recommendations, | ||
}); | ||
}; | ||
|
||
export const handle = { | ||
breadcrumb: (match: RouteMatch) => ( | ||
<Link to={`/movies/${match.params.movieId}/recommendations`}>Recommendations</Link> | ||
), | ||
}; | ||
|
||
const RecommendationsPage = () => { | ||
const { movieId } = useParams(); | ||
const { recommendations } = useLoaderData<LoaderData>(); | ||
const navigate = useNavigate(); | ||
const isXs = useMediaQuery(650); | ||
const paginationChangeHandler = (page: number) => | ||
navigate(`/movies/${movieId}/recommendations?page=${page}`); | ||
|
||
return ( | ||
<Row | ||
fluid | ||
justify="center" | ||
align="center" | ||
css={{ | ||
flexDirection: 'column', | ||
'@xsMax': { | ||
paddingLeft: 'calc(var(--nextui-space-sm))', | ||
paddingRight: 'calc(var(--nextui-space-sm))', | ||
}, | ||
'@xs': { | ||
paddingLeft: '88px', | ||
paddingRight: '1rem', | ||
}, | ||
}} | ||
> | ||
{recommendations && recommendations.items && recommendations.items.length > 0 && ( | ||
<> | ||
<MediaList listType="grid" items={recommendations.items} listName="Recommendations" /> | ||
<Pagination | ||
total={recommendations.totalPages} | ||
initialPage={recommendations.page} | ||
shadow | ||
onChange={paginationChangeHandler} | ||
css={{ marginTop: '30px' }} | ||
{...(isXs && { size: 'xs' })} | ||
/> | ||
</> | ||
)} | ||
</Row> | ||
); | ||
}; | ||
|
||
export default RecommendationsPage; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ctuanle ở đây mình có thể return về data mình cần được nơi m 🤟
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Khanhtran47 return gì k hiểu nơi, chỗ lấy data từ routes parent á ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ctuanle kiểu cái m nói chỉ lấy data cần thiết như bên graphQL ý, bên remix cái return ở chỗ loader, mình có thể return cái gì cũng đc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ctuanle m đọc cái bài ni cho dễ hiểu hơn 😅
https://sergiodxa.com/articles/load-only-the-data-you-need-in-remix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Khanhtran47 t nhớ chỗ loader đúng là mình return cái gì cũng được thật 😅