refactor: refactor code a bit
make a hook to abstarct logic from page changes to .prettierrc changes to a couple of imports/exports bunch of screen reader tweaks
This commit is contained in:
parent
64f3896258
commit
57b050f196
12
.prettierrc
12
.prettierrc
@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"tabWidth": 2,
|
"tabWidth": 2,
|
||||||
"semi": false,
|
"arrowParens": "avoid",
|
||||||
"singleQuote": true
|
"semi": true,
|
||||||
}
|
"singleQuote": true,
|
||||||
|
"jsxSingleQuote": true
|
||||||
|
}
|
||||||
|
@ -17,9 +17,9 @@ const ThemeToggler = (props: Props) => {
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`${styles.button} ${props.className}`}
|
className={`${styles.button} ${props.className}`}
|
||||||
aria-label='Change theme'
|
|
||||||
onClick={clickHandler}
|
onClick={clickHandler}
|
||||||
>
|
>
|
||||||
|
<span className='visually-hidden'>Change theme</span>
|
||||||
<svg
|
<svg
|
||||||
className={`icon ${styles.icon}`}
|
className={`icon ${styles.icon}`}
|
||||||
focusable='false'
|
focusable='false'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Layout from '../../layouts/Layout';
|
import Layout from '../../layouts/Layout';
|
||||||
import Meta from '../Meta/Meta';
|
import Meta from '../meta/Meta';
|
||||||
|
|
||||||
import styles from '../../styles/modules/components/error/error-info.module.scss';
|
import styles from '../../styles/modules/components/error/error-info.module.scss';
|
||||||
|
|
||||||
@ -13,22 +13,22 @@ const ErrorInfo = ({ message = 'Not found, sorry.', statusCode = 404 }) => {
|
|||||||
<>
|
<>
|
||||||
<Meta
|
<Meta
|
||||||
title={`${message} (${statusCode})`}
|
title={`${message} (${statusCode})`}
|
||||||
description='you encountered an error page!'
|
description="you encountered an error page!"
|
||||||
/>
|
/>
|
||||||
<Layout className={styles.error}>
|
<Layout className={styles.error}>
|
||||||
<svg
|
<svg
|
||||||
className={styles.gnu}
|
className={styles.gnu}
|
||||||
focusable='false'
|
focusable="false"
|
||||||
role='img'
|
role="img"
|
||||||
aria-labelledby='gnu-title gnu-desc'
|
aria-labelledby="gnu-title gnu-desc"
|
||||||
>
|
>
|
||||||
<title id='gnu-title'>GNU and Tux</title>
|
<title id="gnu-title">GNU and Tux</title>
|
||||||
<desc id='gnu-desc'>
|
<desc id="gnu-desc">
|
||||||
A pencil drawing of a big gnu and a small penguin, both very sad.
|
A pencil drawing of a big gnu and a small penguin, both very sad.
|
||||||
GNU is despondently sitting on a bench, and Tux stands beside him,
|
GNU is despondently sitting on a bench, and Tux stands beside him,
|
||||||
looking down and patting him on the back.
|
looking down and patting him on the back.
|
||||||
</desc>
|
</desc>
|
||||||
<use href='/svg/sadgnu.svg#sad-gnu'></use>
|
<use href="/svg/sadgnu.svg#sad-gnu"></use>
|
||||||
</svg>
|
</svg>
|
||||||
<h1 className={`heading heading__primary ${styles.heading}`}>
|
<h1 className={`heading heading__primary ${styles.heading}`}>
|
||||||
<span>{message}</span>
|
<span>{message}</span>
|
||||||
@ -36,8 +36,8 @@ const ErrorInfo = ({ message = 'Not found, sorry.', statusCode = 404 }) => {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className={styles.back}>
|
<p className={styles.back}>
|
||||||
Go back to{' '}
|
Go back to{' '}
|
||||||
<Link href='/about'>
|
<Link href="/about">
|
||||||
<a className='link'>the homepage</a>
|
<a className="link">the homepage</a>
|
||||||
</Link>
|
</Link>
|
||||||
.
|
.
|
||||||
</p>
|
</p>
|
@ -1,27 +1,27 @@
|
|||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react';
|
||||||
import Image from 'next/future/image'
|
import Image from 'next/future/image';
|
||||||
import Link from 'next/link'
|
import Link from 'next/link';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
formatNumber,
|
formatNumber,
|
||||||
formatTime,
|
formatTime,
|
||||||
getProxiedIMDbImgUrl,
|
getProxiedIMDbImgUrl,
|
||||||
modifyIMDbImg,
|
modifyIMDbImg,
|
||||||
} from '../../utils/helpers'
|
} from '../../utils/helpers';
|
||||||
import { Basic } from '../../interfaces/shared/title'
|
import { Basic } from '../../interfaces/shared/title';
|
||||||
import styles from '../../styles/modules/components/title/basic.module.scss'
|
import styles from '../../styles/modules/components/title/basic.module.scss';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className: string
|
className: string;
|
||||||
data: Basic
|
data: Basic;
|
||||||
}
|
};
|
||||||
|
|
||||||
const Basic = ({ data, className }: Props) => {
|
const Basic = ({ data, className }: Props) => {
|
||||||
const titleType = data.type.id
|
const titleType = data.type.id;
|
||||||
const releaseTime =
|
const releaseTime =
|
||||||
titleType === 'tvSeries'
|
titleType === 'tvSeries'
|
||||||
? `${data.releaseYear?.start}-${data.releaseYear?.end || 'present'}`
|
? `${data.releaseYear?.start}-${data.releaseYear?.end || 'present'}`
|
||||||
: data.releaseYear?.start
|
: data.releaseYear?.start;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
@ -45,11 +45,11 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
alt={data.poster.caption}
|
alt={data.poster.caption}
|
||||||
priority
|
priority
|
||||||
fill
|
fill
|
||||||
sizes="300px"
|
sizes='300px'
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<svg className={styles.image__NA}>
|
<svg className={styles.image__NA}>
|
||||||
<use href="/svg/sprite.svg#icon-image-slash" />
|
<use href='/svg/sprite.svg#icon-image-slash' />
|
||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -57,7 +57,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
<h1 className={`${styles.title} heading heading__primary`}>
|
<h1 className={`${styles.title} heading heading__primary`}>
|
||||||
{data.title}
|
{data.title}
|
||||||
</h1>
|
</h1>
|
||||||
<ul className={styles.meta} aria-label="quick facts">
|
<ul className={styles.meta} aria-label='quick facts'>
|
||||||
{data.status && data.status.id !== 'released' && (
|
{data.status && data.status.id !== 'released' && (
|
||||||
<li className={styles.meta__text}>{data.status.text}</li>
|
<li className={styles.meta__text}>{data.status.text}</li>
|
||||||
)}
|
)}
|
||||||
@ -78,7 +78,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
<p className={styles.rating}>
|
<p className={styles.rating}>
|
||||||
<span className={styles.rating__num}>{data.ratings.avg}</span>
|
<span className={styles.rating__num}>{data.ratings.avg}</span>
|
||||||
<svg className={styles.rating__icon}>
|
<svg className={styles.rating__icon}>
|
||||||
<use href="/svg/sprite.svg#icon-rating"></use>
|
<use href='/svg/sprite.svg#icon-rating'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<span className={styles.rating__text}> Avg. rating</span>
|
<span className={styles.rating__text}> Avg. rating</span>
|
||||||
</p>
|
</p>
|
||||||
@ -87,7 +87,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
{formatNumber(data.ratings.numVotes)}
|
{formatNumber(data.ratings.numVotes)}
|
||||||
</span>
|
</span>
|
||||||
<svg className={styles.rating__icon}>
|
<svg className={styles.rating__icon}>
|
||||||
<use href="/svg/sprite.svg#icon-like-dislike"></use>
|
<use href='/svg/sprite.svg#icon-like-dislike'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<span className={styles.rating__text}> No. of votes</span>
|
<span className={styles.rating__text}> No. of votes</span>
|
||||||
</p>
|
</p>
|
||||||
@ -99,7 +99,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
{formatNumber(data.ranking.position)}
|
{formatNumber(data.ranking.position)}
|
||||||
</span>
|
</span>
|
||||||
<svg className={styles.rating__icon}>
|
<svg className={styles.rating__icon}>
|
||||||
<use href="/svg/sprite.svg#icon-graph-rising"></use>
|
<use href='/svg/sprite.svg#icon-graph-rising'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<span className={styles.rating__text}>
|
<span className={styles.rating__text}>
|
||||||
{' '}
|
{' '}
|
||||||
@ -136,7 +136,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
<span className={styles.overview__text}>{data.plot || '-'}</span>
|
<span className={styles.overview__text}>{data.plot || '-'}</span>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
{data.primaryCrew.map((crewType) => (
|
{data.primaryCrew.map(crewType => (
|
||||||
<p className={styles.crewType} key={crewType.type.id}>
|
<p className={styles.crewType} key={crewType.type.id}>
|
||||||
<span className={styles.crewType__heading}>
|
<span className={styles.crewType__heading}>
|
||||||
{`${crewType.type.category}: `}
|
{`${crewType.type.category}: `}
|
||||||
@ -153,7 +153,7 @@ const Basic = ({ data, className }: Props) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Basic
|
export default Basic;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { NextRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Info } from '../../interfaces/shared/title';
|
import { Info } from '../../interfaces/shared/title';
|
||||||
import { formatMoney, formatTime } from '../../utils/helpers';
|
import { formatMoney, formatTime } from '../../utils/helpers';
|
||||||
|
|
||||||
@ -8,10 +8,10 @@ import styles from '../../styles/modules/components/title/info.module.scss';
|
|||||||
type Props = {
|
type Props = {
|
||||||
info: Info;
|
info: Info;
|
||||||
className: string;
|
className: string;
|
||||||
router: NextRouter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Info = ({ info, className, router }: Props) => {
|
const Info = ({ info, className }: Props) => {
|
||||||
|
const router = useRouter();
|
||||||
const { titleId } = router.query;
|
const { titleId } = router.query;
|
||||||
const { boxOffice, details, meta, keywords, technicalSpecs, accolades } =
|
const { boxOffice, details, meta, keywords, technicalSpecs, accolades } =
|
||||||
info;
|
info;
|
||||||
@ -20,7 +20,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<div className={`${className} ${styles.info}`}>
|
<div className={`${className} ${styles.info}`}>
|
||||||
{meta.infoEpisode && (
|
{meta.infoEpisode && (
|
||||||
<section className={styles.episodeInfo}>
|
<section className={styles.episodeInfo}>
|
||||||
<h2 className='heading heading__secondary'>Episode info</h2>
|
<h2 className="heading heading__secondary">Episode info</h2>
|
||||||
<div className={styles.episodeInfo__container}>
|
<div className={styles.episodeInfo__container}>
|
||||||
{meta.infoEpisode.numSeason && (
|
{meta.infoEpisode.numSeason && (
|
||||||
<p className={styles.series}>
|
<p className={styles.series}>
|
||||||
@ -50,14 +50,14 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
{meta.infoEpisode.prevId && (
|
{meta.infoEpisode.prevId && (
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${meta.infoEpisode.prevId}`}>
|
<Link href={`/title/${meta.infoEpisode.prevId}`}>
|
||||||
<a className='link'>Go to previous episode</a>
|
<a className="link">Go to previous episode</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{meta.infoEpisode.nextId && (
|
{meta.infoEpisode.nextId && (
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${meta.infoEpisode.nextId}`}>
|
<Link href={`/title/${meta.infoEpisode.nextId}`}>
|
||||||
<a className='link'>Go to next episode</a>
|
<a className="link">Go to next episode</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@ -66,7 +66,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{meta.infoSeries && (
|
{meta.infoSeries && (
|
||||||
<section className={styles.seriesInfo}>
|
<section className={styles.seriesInfo}>
|
||||||
<h2 className='heading heading__secondary'>Series info</h2>
|
<h2 className="heading heading__secondary">Series info</h2>
|
||||||
<div className={styles.seriesInfo__container}>
|
<div className={styles.seriesInfo__container}>
|
||||||
<p>
|
<p>
|
||||||
<span>Total Seasons: </span>
|
<span>Total Seasons: </span>
|
||||||
@ -82,19 +82,19 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${titleId}/episodes`}>
|
<Link href={`/title/${titleId}/episodes`}>
|
||||||
<a className='link'>See all Episodes</a>
|
<a className="link">See all Episodes</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
<section className={styles.accolades}>
|
<section className={styles.accolades}>
|
||||||
<h2 className='heading heading__secondary'>Accolades</h2>
|
<h2 className="heading heading__secondary">Accolades</h2>
|
||||||
<div className={styles.accolades__container}>
|
<div className={styles.accolades__container}>
|
||||||
{accolades.topRating && (
|
{accolades.topRating && (
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/chart/top`}>
|
<Link href={`/chart/top`}>
|
||||||
<a className='link'>Top rated (#{accolades.topRating})</a>
|
<a className="link">Top rated (#{accolades.topRating})</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@ -112,21 +112,21 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${titleId}/awards`}>
|
<Link href={`/title/${titleId}/awards`}>
|
||||||
<a className='link'>View all awards</a>
|
<a className="link">View all awards</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{!!keywords.total && (
|
{!!keywords.total && (
|
||||||
<section className={styles.keywords}>
|
<section className={styles.keywords}>
|
||||||
<h2 className='heading heading__secondary'>Keywords</h2>
|
<h2 className="heading heading__secondary">Keywords</h2>
|
||||||
<ul className={styles.keywords__container}>
|
<ul className={styles.keywords__container}>
|
||||||
{keywords.list.map(word => (
|
{keywords.list.map(word => (
|
||||||
<li className={styles.keywords__item} key={word}>
|
<li className={styles.keywords__item} key={word}>
|
||||||
<Link
|
<Link
|
||||||
href={`/search/keyword/?keywords=${word.replace(/\s/g,'-')}`}
|
href={`/search/keyword/?keywords=${word.replace(/\s/g, '-')}`}
|
||||||
>
|
>
|
||||||
<a className='link'>{word}</a>
|
<a className="link">{word}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
@ -135,7 +135,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{!!Object.keys(details).length && (
|
{!!Object.keys(details).length && (
|
||||||
<section className={styles.details}>
|
<section className={styles.details}>
|
||||||
<h2 className='heading heading__secondary'>Details</h2>
|
<h2 className="heading heading__secondary">Details</h2>
|
||||||
<div className={styles.details__container}>
|
<div className={styles.details__container}>
|
||||||
{details.releaseDate && (
|
{details.releaseDate && (
|
||||||
<p>
|
<p>
|
||||||
@ -156,7 +156,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<Link
|
<Link
|
||||||
href={`/search/title/?country_of_origin=${country.id}`}
|
href={`/search/title/?country_of_origin=${country.id}`}
|
||||||
>
|
>
|
||||||
<a className='link'>{country.text}</a>
|
<a className="link">{country.text}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
@ -168,7 +168,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
{details.officialSites.sites.map((site, i) => (
|
{details.officialSites.sites.map((site, i) => (
|
||||||
<span key={site.url}>
|
<span key={site.url}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<a href={site.url} className='link'>
|
<a href={site.url} className="link">
|
||||||
{site.name}
|
{site.name}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
@ -182,7 +182,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<span key={lang.id}>
|
<span key={lang.id}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<Link href={`/search/title/?primary_language=${lang.id}`}>
|
<Link href={`/search/title/?primary_language=${lang.id}`}>
|
||||||
<a className='link'>{lang.text}</a>
|
<a className="link">{lang.text}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
@ -201,7 +201,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<span key={loc}>
|
<span key={loc}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<Link href={`/search/title/?locations=${loc}`}>
|
<Link href={`/search/title/?locations=${loc}`}>
|
||||||
<a className='link'>{loc}</a>
|
<a className="link">{loc}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
@ -214,7 +214,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<span key={co.id}>
|
<span key={co.id}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<Link href={`/company/${co.id}`}>
|
<Link href={`/company/${co.id}`}>
|
||||||
<a className='link'>{co.name}</a>
|
<a className="link">{co.name}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
@ -225,7 +225,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{!!Object.keys(boxOffice).length && (
|
{!!Object.keys(boxOffice).length && (
|
||||||
<section className={styles.boxoffice}>
|
<section className={styles.boxoffice}>
|
||||||
<h2 className='heading heading__secondary'>Box office</h2>
|
<h2 className="heading heading__secondary">Box office</h2>
|
||||||
<div className={styles.boxoffice__container}>
|
<div className={styles.boxoffice__container}>
|
||||||
{boxOffice.budget && (
|
{boxOffice.budget && (
|
||||||
<p>
|
<p>
|
||||||
@ -277,7 +277,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{!!Object.keys(technicalSpecs).length && (
|
{!!Object.keys(technicalSpecs).length && (
|
||||||
<section className={styles.technical}>
|
<section className={styles.technical}>
|
||||||
<h2 className='heading heading__secondary'>Technical specs</h2>
|
<h2 className="heading heading__secondary">Technical specs</h2>
|
||||||
<div className={styles.technical__container}>
|
<div className={styles.technical__container}>
|
||||||
{technicalSpecs.runtime && (
|
{technicalSpecs.runtime && (
|
||||||
<p>
|
<p>
|
||||||
@ -293,7 +293,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<span key={color.id}>
|
<span key={color.id}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<Link href={`/search/title/?colors=${color.id}`}>
|
<Link href={`/search/title/?colors=${color.id}`}>
|
||||||
<a className='link'>{color.name}</a>
|
<a className="link">{color.name}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
@ -308,7 +308,7 @@ const Info = ({ info, className, router }: Props) => {
|
|||||||
<span key={sound.id}>
|
<span key={sound.id}>
|
||||||
{!!i && ', '}
|
{!!i && ', '}
|
||||||
<Link href={`/search/title/?sound_mixes=${sound.id}`}>
|
<Link href={`/search/title/?sound_mixes=${sound.id}`}>
|
||||||
<a className='link'>{sound.name}</a>
|
<a className="link">{sound.name}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import Image from 'next/future/image';
|
import Image from 'next/future/image';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { NextRouter } from 'next/router';
|
|
||||||
import { Media } from '../../interfaces/shared/title';
|
import { Media } from '../../interfaces/shared/title';
|
||||||
import { getProxiedIMDbImgUrl, modifyIMDbImg } from '../../utils/helpers';
|
import { getProxiedIMDbImgUrl, modifyIMDbImg } from '../../utils/helpers';
|
||||||
|
|
||||||
@ -9,21 +8,20 @@ import styles from '../../styles/modules/components/title/media.module.scss';
|
|||||||
type Props = {
|
type Props = {
|
||||||
className: string;
|
className: string;
|
||||||
media: Media;
|
media: Media;
|
||||||
router: NextRouter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Media = ({ className, media, router }: Props) => {
|
const Media = ({ className, media }: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className={`${className} ${styles.media}`}>
|
<div className={`${className} ${styles.media}`}>
|
||||||
{(media.trailer || !!media.videos.total) && (
|
{(media.trailer || !!media.videos.total) && (
|
||||||
<section className={styles.videos}>
|
<section className={styles.videos}>
|
||||||
<h2 className="heading heading__secondary">Videos</h2>
|
<h2 className='heading heading__secondary'>Videos</h2>
|
||||||
|
|
||||||
<div className={styles.videos__container}>
|
<div className={styles.videos__container}>
|
||||||
{media.trailer && (
|
{media.trailer && (
|
||||||
<div key={router.asPath} className={styles.trailer}>
|
<div className={styles.trailer}>
|
||||||
<video
|
<video
|
||||||
aria-label="trailer video"
|
aria-label='trailer video'
|
||||||
// it's a relatively new tag. hence jsx-all1 complains
|
// it's a relatively new tag. hence jsx-all1 complains
|
||||||
aria-description={media.trailer.caption}
|
aria-description={media.trailer.caption}
|
||||||
controls
|
controls
|
||||||
@ -32,7 +30,7 @@ const Media = ({ className, media, router }: Props) => {
|
|||||||
modifyIMDbImg(media.trailer.thumbnail)
|
modifyIMDbImg(media.trailer.thumbnail)
|
||||||
)}
|
)}
|
||||||
className={styles.trailer__video}
|
className={styles.trailer__video}
|
||||||
preload="none"
|
preload='none'
|
||||||
>
|
>
|
||||||
{media.trailer.urls.map(source => (
|
{media.trailer.urls.map(source => (
|
||||||
<source
|
<source
|
||||||
@ -53,9 +51,9 @@ const Media = ({ className, media, router }: Props) => {
|
|||||||
<Image
|
<Image
|
||||||
className={styles.video__img}
|
className={styles.video__img}
|
||||||
src={modifyIMDbImg(video.thumbnail)}
|
src={modifyIMDbImg(video.thumbnail)}
|
||||||
alt=""
|
alt=''
|
||||||
fill
|
fill
|
||||||
sizes="400px"
|
sizes='400px'
|
||||||
/>
|
/>
|
||||||
<p className={styles.video__caption}>
|
<p className={styles.video__caption}>
|
||||||
{video.caption} ({video.runtime}s)
|
{video.caption} ({video.runtime}s)
|
||||||
@ -68,16 +66,16 @@ const Media = ({ className, media, router }: Props) => {
|
|||||||
)}
|
)}
|
||||||
{!!media.images.total && (
|
{!!media.images.total && (
|
||||||
<section className={styles.images}>
|
<section className={styles.images}>
|
||||||
<h2 className="heading heading__secondary">Images</h2>
|
<h2 className='heading heading__secondary'>Images</h2>
|
||||||
<div className={styles.images__container}>
|
<div className={styles.images__container}>
|
||||||
{media.images.images.map(image => (
|
{media.images.images.map(image => (
|
||||||
<figure key={image.id} className={styles.image}>
|
<figure key={image.id} className={styles.image}>
|
||||||
<Image
|
<Image
|
||||||
className={styles.image__img}
|
className={styles.image__img}
|
||||||
src={modifyIMDbImg(image.url)}
|
src={modifyIMDbImg(image.url)}
|
||||||
alt=""
|
alt=''
|
||||||
fill
|
fill
|
||||||
sizes="400px"
|
sizes='400px'
|
||||||
/>
|
/>
|
||||||
<figcaption className={styles.image__caption}>
|
<figcaption className={styles.image__caption}>
|
||||||
{image.caption.plainText}
|
{image.caption.plainText}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { NextRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { Reviews } from '../../interfaces/shared/title';
|
import { Reviews } from '../../interfaces/shared/title';
|
||||||
import { formatNumber } from '../../utils/helpers';
|
import { formatNumber } from '../../utils/helpers';
|
||||||
@ -6,15 +6,15 @@ import styles from '../../styles/modules/components/title/reviews.module.scss';
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
reviews: Reviews;
|
reviews: Reviews;
|
||||||
router: NextRouter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Reviews = ({ reviews, router }: Props) => {
|
const Reviews = ({ reviews }: Props) => {
|
||||||
|
const router = useRouter();
|
||||||
const { titleId } = router.query;
|
const { titleId } = router.query;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.reviews}>
|
<section className={styles.reviews}>
|
||||||
<h2 className='heading heading__secondary'>Reviews</h2>
|
<h2 className="heading heading__secondary">Reviews</h2>
|
||||||
|
|
||||||
{reviews.featuredReview && (
|
{reviews.featuredReview && (
|
||||||
<article className={styles.reviews__reviewContainer}>
|
<article className={styles.reviews__reviewContainer}>
|
||||||
@ -38,7 +38,7 @@ const Reviews = ({ reviews, router }: Props) => {
|
|||||||
{' '}
|
{' '}
|
||||||
by{' '}
|
by{' '}
|
||||||
<Link href={`/user/${reviews.featuredReview.reviewer.id}`}>
|
<Link href={`/user/${reviews.featuredReview.reviewer.id}`}>
|
||||||
<a className='link'>{reviews.featuredReview.reviewer.name}</a>
|
<a className="link">{reviews.featuredReview.reviewer.name}</a>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<span> on {reviews.featuredReview.date}.</span>
|
<span> on {reviews.featuredReview.date}.</span>
|
||||||
@ -58,21 +58,21 @@ const Reviews = ({ reviews, router }: Props) => {
|
|||||||
<div className={styles.reviews__stats}>
|
<div className={styles.reviews__stats}>
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${titleId}/reviews`}>
|
<Link href={`/title/${titleId}/reviews`}>
|
||||||
<a className='link'>
|
<a className="link">
|
||||||
{formatNumber(reviews.numUserReviews)} User reviews
|
{formatNumber(reviews.numUserReviews)} User reviews
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${titleId}/externalreviews`}>
|
<Link href={`/title/${titleId}/externalreviews`}>
|
||||||
<a className='link'>
|
<a className="link">
|
||||||
{formatNumber(reviews.numCriticReviews)} Critic reviews
|
{formatNumber(reviews.numCriticReviews)} Critic reviews
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<Link href={`/title/${titleId}/criticreviews`}>
|
<Link href={`/title/${titleId}/criticreviews`}>
|
||||||
<a className='link'> {reviews.metacriticScore} Metascore</a>
|
<a className="link"> {reviews.metacriticScore} Metascore</a>
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
9
src/components/title/index.tsx
Normal file
9
src/components/title/index.tsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import Basic from './Basic';
|
||||||
|
import Cast from './Cast';
|
||||||
|
import DidYouKnow from './DidYouKnow';
|
||||||
|
import Info from './Info';
|
||||||
|
import Media from './Media';
|
||||||
|
import MoreLikeThis from './MoreLikeThis';
|
||||||
|
import Reviews from './Reviews';
|
||||||
|
|
||||||
|
export { Basic, Cast, DidYouKnow, Info, Media, MoreLikeThis, Reviews };
|
31
src/hooks/usePageLoading.ts
Normal file
31
src/hooks/usePageLoading.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for showing progress bar. could've used nprogress package, but didn't feel like it
|
||||||
|
* @returns isPageLoading: as the name suggests.
|
||||||
|
* @returns key: a unique key(in reality, a part of url) telling whether the page has changed or not
|
||||||
|
*/
|
||||||
|
const useIsPageLoading = () => {
|
||||||
|
const router = useRouter();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
const handleStart = useCallback(() => setIsLoading(true), []);
|
||||||
|
const handleEnd = useCallback(() => setIsLoading(false), []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
router.events.on('routeChangeStart', handleStart);
|
||||||
|
router.events.on('routeChangeComplete', handleEnd);
|
||||||
|
router.events.on('routeChangeError', handleEnd);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
router.events.off('routeChangeStart', handleStart);
|
||||||
|
router.events.off('routeChangeComplete', handleEnd);
|
||||||
|
router.events.off('routeChangeError', handleEnd);
|
||||||
|
};
|
||||||
|
}, [router, handleStart, handleEnd]);
|
||||||
|
|
||||||
|
return { isPageLoading: isLoading, key: router.asPath };
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useIsPageLoading;
|
@ -1,4 +1,4 @@
|
|||||||
import ErrorInfo from '../components/Error/ErrorInfo';
|
import ErrorInfo from '../components/error/ErrorInfo';
|
||||||
|
|
||||||
const Error404 = () => {
|
const Error404 = () => {
|
||||||
return <ErrorInfo />;
|
return <ErrorInfo />;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import ErrorInfo from '../components/Error/ErrorInfo';
|
import ErrorInfo from '../components/error/ErrorInfo';
|
||||||
|
|
||||||
const Error500 = () => {
|
const Error500 = () => {
|
||||||
return <ErrorInfo message='server messed up, sorry.' statusCode={500} />;
|
return <ErrorInfo message="server messed up, sorry." statusCode={500} />;
|
||||||
};
|
};
|
||||||
export default Error500;
|
export default Error500;
|
||||||
|
@ -1,38 +1,21 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
|
||||||
import type { AppProps } from 'next/app';
|
import type { AppProps } from 'next/app';
|
||||||
import { useRouter } from 'next/router';
|
import usePageLoading from '../hooks/usePageLoading';
|
||||||
|
|
||||||
import ProgressBar from '../components/loaders/ProgressBar';
|
import ProgressBar from '../components/loaders/ProgressBar';
|
||||||
import ThemeProvider from '../context/theme-context';
|
import ThemeProvider from '../context/theme-context';
|
||||||
|
|
||||||
import '../styles/main.scss';
|
import '../styles/main.scss';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
const ModifiedApp = ({ Component, pageProps }: AppProps) => {
|
const ModifiedApp = ({ Component, pageProps }: AppProps) => {
|
||||||
// for showing progress bar
|
const { isPageLoading, key } = usePageLoading();
|
||||||
// could've used nprogress package, but didn't feel like it
|
|
||||||
const router = useRouter();
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const handleStart = useCallback(() => setIsLoading(true), []);
|
|
||||||
const handleEnd = useCallback(() => setIsLoading(false), []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
router.events.on('routeChangeStart', handleStart);
|
|
||||||
router.events.on('routeChangeComplete', handleEnd);
|
|
||||||
router.events.on('routeChangeError', handleEnd);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
router.events.off('routeChangeStart', handleStart);
|
|
||||||
router.events.off('routeChangeComplete', handleEnd);
|
|
||||||
router.events.off('routeChangeError', handleEnd);
|
|
||||||
};
|
|
||||||
}, [router, handleStart, handleEnd]);
|
|
||||||
//
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
{isLoading && <ProgressBar />}
|
{isPageLoading && <ProgressBar />}
|
||||||
<Component {...pageProps} />
|
<Component
|
||||||
|
{...pageProps}
|
||||||
|
key={key} /* passing key to force react to remound components */
|
||||||
|
/>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -3,15 +3,17 @@ import Document, { Html, Head, Main, NextScript } from 'next/document';
|
|||||||
// for preventing Flash of inAccurate coloR Theme(fart)
|
// for preventing Flash of inAccurate coloR Theme(fart)
|
||||||
// chris coyier came up with that acronym(https://css-tricks.com/flash-of-inaccurate-color-theme-fart/)
|
// chris coyier came up with that acronym(https://css-tricks.com/flash-of-inaccurate-color-theme-fart/)
|
||||||
const setInitialTheme = `
|
const setInitialTheme = `
|
||||||
document.documentElement.dataset.js = true;
|
(() => {
|
||||||
document.documentElement.dataset.theme = (() => {
|
document.documentElement.dataset.js = true;
|
||||||
|
let theme = 'light';
|
||||||
|
let themeColor = '#ffe5ef';
|
||||||
const userPrefersTheme = window.localStorage.getItem('theme') || null;
|
const userPrefersTheme = window.localStorage.getItem('theme') || null;
|
||||||
const browserPrefersDarkTheme = window.matchMedia(
|
const browserPrefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
'(prefers-color-scheme: dark)'
|
if (userPrefersTheme) theme = userPrefersTheme;
|
||||||
).matches;
|
else if (browserPrefersDarkTheme) theme = 'dark';
|
||||||
if (userPrefersTheme) return userPrefersTheme;
|
if(theme === 'dark') themeColor = '#141c2e';
|
||||||
else if (browserPrefersDarkTheme) return 'dark';
|
document.documentElement.dataset.theme = theme;
|
||||||
else return 'light';
|
document.querySelector('meta[name="theme-color"]').setAttribute('content', themeColor);
|
||||||
})();
|
})();
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
/* eslint-disable react/no-unescaped-entities */
|
/* eslint-disable react/no-unescaped-entities */
|
||||||
import Link from 'next/link'
|
import Link from 'next/link';
|
||||||
import Meta from '../../components/Meta/Meta'
|
import Meta from '../../components/meta/Meta';
|
||||||
import Layout from '../../layouts/Layout'
|
import Layout from '../../layouts/Layout';
|
||||||
|
|
||||||
import styles from '../../styles/modules/pages/about/about.module.scss'
|
import styles from '../../styles/modules/pages/about/about.module.scss';
|
||||||
|
|
||||||
const About = () => {
|
const About = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Meta
|
<Meta
|
||||||
title="About"
|
title='About'
|
||||||
description="libremdb is a free & open source IMDb front-end. It allows you to see information about movies, tv shows, video games without any ads or tracking."
|
description='libremdb is a free & open source IMDb front-end. It allows you to see information about movies, tv shows, video games without any ads or tracking.'
|
||||||
/>
|
/>
|
||||||
<Layout full className={styles.about}>
|
<Layout full className={styles.about}>
|
||||||
<section id="features" className={styles.features}>
|
<section id='features' className={styles.features}>
|
||||||
<h2
|
<h2
|
||||||
className={`heading heading__secondary ${styles.features__heading}`}
|
className={`heading heading__secondary ${styles.features__heading}`}
|
||||||
>
|
>
|
||||||
@ -22,12 +22,12 @@ const About = () => {
|
|||||||
<ul className={styles.features__list}>
|
<ul className={styles.features__list}>
|
||||||
<li className={styles.feature}>
|
<li className={styles.feature}>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden='true'
|
||||||
focusable="false"
|
focusable='false'
|
||||||
role="img"
|
role='img'
|
||||||
className={styles.feature__icon}
|
className={styles.feature__icon}
|
||||||
>
|
>
|
||||||
<use href="/svg/sprite.svg#icon-eye-slash"></use>
|
<use href='/svg/sprite.svg#icon-eye-slash'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<h3
|
<h3
|
||||||
className={`heading heading__tertiary ${styles.feature__heading}`}
|
className={`heading heading__tertiary ${styles.feature__heading}`}
|
||||||
@ -41,12 +41,12 @@ const About = () => {
|
|||||||
</li>
|
</li>
|
||||||
<li className={styles.feature}>
|
<li className={styles.feature}>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden='true'
|
||||||
focusable="false"
|
focusable='false'
|
||||||
role="img"
|
role='img'
|
||||||
className={styles.feature__icon}
|
className={styles.feature__icon}
|
||||||
>
|
>
|
||||||
<use href="/svg/sprite.svg#icon-palette"></use>
|
<use href='/svg/sprite.svg#icon-palette'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<h3
|
<h3
|
||||||
className={`heading heading__tertiary ${styles.feature__heading}`}
|
className={`heading heading__tertiary ${styles.feature__heading}`}
|
||||||
@ -60,12 +60,12 @@ const About = () => {
|
|||||||
</li>
|
</li>
|
||||||
<li className={styles.feature}>
|
<li className={styles.feature}>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden='true'
|
||||||
focusable="false"
|
focusable='false'
|
||||||
role="img"
|
role='img'
|
||||||
className={styles.feature__icon}
|
className={styles.feature__icon}
|
||||||
>
|
>
|
||||||
<use href="/svg/sprite.svg#icon-responsive"></use>
|
<use href='/svg/sprite.svg#icon-responsive'></use>
|
||||||
</svg>
|
</svg>
|
||||||
<h3
|
<h3
|
||||||
className={`heading heading__tertiary ${styles.feature__heading}`}
|
className={`heading heading__tertiary ${styles.feature__heading}`}
|
||||||
@ -79,7 +79,7 @@ const About = () => {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
<section id="faq" className={styles.faqs}>
|
<section id='faq' className={styles.faqs}>
|
||||||
<h2 className={`heading heading__secondary ${styles.faqs__heading}`}>
|
<h2 className={`heading heading__secondary ${styles.faqs__heading}`}>
|
||||||
Questions you may have
|
Questions you may have
|
||||||
</h2>
|
</h2>
|
||||||
@ -91,21 +91,25 @@ const About = () => {
|
|||||||
<p className={styles.faq__description}>
|
<p className={styles.faq__description}>
|
||||||
Replace `imdb.com` in any IMDb URL with any of the instances.
|
Replace `imdb.com` in any IMDb URL with any of the instances.
|
||||||
For example: `
|
For example: `
|
||||||
<a href="https://imdb.com/title/tt1049413" className="link">
|
<a
|
||||||
|
href='https://imdb.com/title/tt1049413'
|
||||||
|
className='link'
|
||||||
|
target='_blank'
|
||||||
|
rel='noreferrer'
|
||||||
|
>
|
||||||
imdb.com/title/tt1049413
|
imdb.com/title/tt1049413
|
||||||
</a>
|
</a>
|
||||||
` to `
|
` to `
|
||||||
<a
|
<Link href='/title/tt1049413'>
|
||||||
href="https://libremdb.iket.me/title/tt1049413"
|
<a className='link'>
|
||||||
className="link"
|
{process.env.NEXT_PUBLIC_URL || ''}/title/tt1049413
|
||||||
>
|
</a>
|
||||||
libremdb.iket.me/title/tt1049413
|
</Link>
|
||||||
</a>
|
|
||||||
` . To avoid changing the URLs manually, you can use extensions
|
` . To avoid changing the URLs manually, you can use extensions
|
||||||
like{' '}
|
like{' '}
|
||||||
<a
|
<a
|
||||||
href="https://github.com/libredirect/libredirect/"
|
href='https://github.com/libredirect/libredirect/'
|
||||||
className="link"
|
className='link'
|
||||||
>
|
>
|
||||||
LibRedirect
|
LibRedirect
|
||||||
</a>
|
</a>
|
||||||
@ -140,33 +144,23 @@ const About = () => {
|
|||||||
instance to avoid exposing your IP address, browser information
|
instance to avoid exposing your IP address, browser information
|
||||||
and other personally identifiable metadata (
|
and other personally identifiable metadata (
|
||||||
<a
|
<a
|
||||||
href="https://github.com/httpjamesm"
|
href='https://github.com/httpjamesm'
|
||||||
target="_blank"
|
target='_blank'
|
||||||
rel="noopener noreferrer"
|
rel='noopener noreferrer'
|
||||||
className="link"
|
className='link'
|
||||||
>
|
>
|
||||||
Contributor
|
Contributor
|
||||||
</a>
|
</a>
|
||||||
).
|
).
|
||||||
</p>
|
</p>
|
||||||
</details>
|
</details>
|
||||||
<details className={styles.faq}>
|
|
||||||
<summary className={styles.faq__summary}>
|
|
||||||
Will Amazon track me then?
|
|
||||||
</summary>
|
|
||||||
<p className={styles.faq__description}>
|
|
||||||
Also nope. All Amazon will see is the libremdb instance making
|
|
||||||
the request, not you. IP address, browser information and other
|
|
||||||
personally identifiable metadata is hidden from Amazon.
|
|
||||||
</p>
|
|
||||||
</details>
|
|
||||||
<details className={styles.faq}>
|
<details className={styles.faq}>
|
||||||
<summary className={styles.faq__summary}>
|
<summary className={styles.faq__summary}>
|
||||||
Why not just use IMDb?
|
Why not just use IMDb?
|
||||||
</summary>
|
</summary>
|
||||||
<p className={styles.faq__description}>
|
<p className={styles.faq__description}>
|
||||||
Refer to the{' '}
|
Refer to the{' '}
|
||||||
<a className="link" href="#features">
|
<a className='link' href='#features'>
|
||||||
features section
|
features section
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
above.
|
above.
|
||||||
@ -196,8 +190,8 @@ const About = () => {
|
|||||||
</summary>
|
</summary>
|
||||||
<p className={styles.faq__description}>
|
<p className={styles.faq__description}>
|
||||||
That's great! I've a couple of{' '}
|
That's great! I've a couple of{' '}
|
||||||
<Link href="/contact">
|
<Link href='/contact'>
|
||||||
<a className="link">contact methods</a>
|
<a className='link'>contact methods</a>
|
||||||
</Link>
|
</Link>
|
||||||
. Send your beautiful suggestions(or complaints), or just drop a
|
. Send your beautiful suggestions(or complaints), or just drop a
|
||||||
hi.
|
hi.
|
||||||
@ -207,7 +201,7 @@ const About = () => {
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default About
|
export default About;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Meta from '../../components/Meta/Meta';
|
import Meta from '../../components/meta/Meta';
|
||||||
import Layout from '../../layouts/Layout';
|
import Layout from '../../layouts/Layout';
|
||||||
|
|
||||||
import styles from '../../styles/modules/pages/contact/contact.module.scss';
|
import styles from '../../styles/modules/pages/contact/contact.module.scss';
|
||||||
@ -7,10 +7,10 @@ const Contact = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Meta
|
<Meta
|
||||||
title='Contact'
|
title="Contact"
|
||||||
description='Contact page of libremdb, a free & open source IMDb front-end.'
|
description="Contact page of libremdb, a free & open source IMDb front-end."
|
||||||
/>
|
/>
|
||||||
<Layout className=''>
|
<Layout className="">
|
||||||
<section className={styles.contact}>
|
<section className={styles.contact}>
|
||||||
<h1 className={`heading heading__primary ${styles.contact__heading}`}>
|
<h1 className={`heading heading__primary ${styles.contact__heading}`}>
|
||||||
Contact
|
Contact
|
||||||
@ -19,22 +19,22 @@ const Contact = () => {
|
|||||||
<div className={styles.list}>
|
<div className={styles.list}>
|
||||||
<p className={styles.item}>
|
<p className={styles.item}>
|
||||||
You can use{' '}
|
You can use{' '}
|
||||||
<a href='https://github.com/zyachel/libremdb' className='link'>
|
<a href="https://github.com/zyachel/libremdb" className="link">
|
||||||
GitHub
|
GitHub
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
or{' '}
|
or{' '}
|
||||||
<a href='https://codeberg.org/zyachel/libremdb' className='link'>
|
<a href="https://codeberg.org/zyachel/libremdb" className="link">
|
||||||
Codeberg
|
Codeberg
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
for general issues, questions, or requests.
|
for general issues, questions, or requests.
|
||||||
</p>
|
</p>
|
||||||
<p className={styles.item}>
|
<p className={styles.item}>
|
||||||
In case you wish to contact me personally, I'm reachable via{' '}
|
In case you wish to contact me personally, I'm reachable via{' '}
|
||||||
<a className='link' href='https://matrix.to/#/@ninal:matrix.org'>
|
<a className="link" href="https://matrix.to/#/@ninal:matrix.org">
|
||||||
[matrix]
|
[matrix]
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
and{' '}
|
and{' '}
|
||||||
<a className='link' href='mailto:aricla@protonmail.com'>
|
<a className="link" href="mailto:aricla@protonmail.com">
|
||||||
email
|
email
|
||||||
</a>
|
</a>
|
||||||
.
|
.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import Meta from '../../components/Meta/Meta'
|
import Meta from '../../components/meta/Meta';
|
||||||
import Layout from '../../layouts/Layout'
|
import Layout from '../../layouts/Layout';
|
||||||
|
|
||||||
import styles from '../../styles/modules/pages/privacy/privacy.module.scss'
|
import styles from '../../styles/modules/pages/privacy/privacy.module.scss';
|
||||||
|
|
||||||
const Privacy = () => {
|
const Privacy = () => {
|
||||||
return (
|
return (
|
||||||
@ -55,7 +55,7 @@ const Privacy = () => {
|
|||||||
</section>
|
</section>
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Privacy
|
export default Privacy;
|
||||||
|
@ -1,35 +1,34 @@
|
|||||||
// external
|
// external
|
||||||
import { GetServerSideProps, GetStaticProps, GetStaticPaths } from 'next'
|
import { GetServerSideProps, GetStaticProps, GetStaticPaths } from 'next'
|
||||||
import { useRouter } from 'next/router'
|
import Head from 'next/head';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
// local
|
// local
|
||||||
import Meta from '../../../components/Meta/Meta'
|
import Meta from '../../../components/meta/Meta';
|
||||||
import Layout from '../../../layouts/Layout'
|
import Layout from '../../../layouts/Layout';
|
||||||
import title from '../../../utils/fetchers/title'
|
import ErrorInfo from '../../../components/error/ErrorInfo';
|
||||||
// components
|
import {
|
||||||
import ErrorInfo from '../../../components/Error/ErrorInfo'
|
Basic,
|
||||||
import Basic from '../../../components/title/Basic'
|
Cast,
|
||||||
import Media from '../../../components/title/Media'
|
DidYouKnow,
|
||||||
import Cast from '../../../components/title/Cast'
|
Info,
|
||||||
import DidYouKnow from '../../../components/title/DidYouKnow'
|
Media,
|
||||||
import Info from '../../../components/title/Info'
|
MoreLikeThis,
|
||||||
import Reviews from '../../../components/title/Reviews'
|
Reviews,
|
||||||
import MoreLikeThis from '../../../components/title/MoreLikeThis'
|
} from '../../../components/title';
|
||||||
// misc
|
// misc
|
||||||
import Title from '../../../interfaces/shared/title'
|
import Title from '../../../interfaces/shared/title';
|
||||||
import { AppError } from '../../../interfaces/shared/error'
|
import { AppError } from '../../../interfaces/shared/error';
|
||||||
|
import title from '../../../utils/fetchers/title';
|
||||||
|
import { getProxiedIMDbImgUrl } from '../../../utils/helpers';
|
||||||
// styles
|
// styles
|
||||||
import styles from '../../../styles/modules/pages/title/title.module.scss'
|
import styles from '../../../styles/modules/pages/title/title.module.scss';
|
||||||
import Head from 'next/head'
|
|
||||||
import { getProxiedIMDbImgUrl } from '../../../utils/helpers'
|
|
||||||
|
|
||||||
type Props = { data: Title; error: null } | { error: AppError; data: null }
|
type Props = { data: Title; error: null } | { error: AppError; data: null };
|
||||||
|
|
||||||
// TO-DO: make a wrapper page component to display errors, if present in props
|
// TO-DO: make a wrapper page component to display errors, if present in props
|
||||||
const TitleInfo = ({ data, error }: Props) => {
|
const TitleInfo = ({ data, error }: Props) => {
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return <ErrorInfo message={error.message} statusCode={error.statusCode} />
|
return <ErrorInfo message={error.message} statusCode={error.statusCode} />;
|
||||||
|
|
||||||
const info = {
|
const info = {
|
||||||
meta: data.meta,
|
meta: data.meta,
|
||||||
@ -38,7 +37,7 @@ const TitleInfo = ({ data, error }: Props) => {
|
|||||||
boxOffice: data.boxOffice,
|
boxOffice: data.boxOffice,
|
||||||
technicalSpecs: data.technicalSpecs,
|
technicalSpecs: data.technicalSpecs,
|
||||||
accolades: data.accolades,
|
accolades: data.accolades,
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -60,18 +59,18 @@ const TitleInfo = ({ data, error }: Props) => {
|
|||||||
</Head>
|
</Head>
|
||||||
<Layout className={styles.title}>
|
<Layout className={styles.title}>
|
||||||
<Basic data={data.basic} className={styles.basic} />
|
<Basic data={data.basic} className={styles.basic} />
|
||||||
<Media className={styles.media} media={data.media} router={router} />
|
<Media className={styles.media} media={data.media} />
|
||||||
<Cast className={styles.cast} cast={data.cast} />
|
<Cast className={styles.cast} cast={data.cast} />
|
||||||
<div className={styles.textarea}>
|
<div className={styles.textarea}>
|
||||||
<DidYouKnow data={data.didYouKnow} />
|
<DidYouKnow data={data.didYouKnow} />
|
||||||
<Reviews reviews={data.reviews} router={router} />
|
<Reviews reviews={data.reviews} />
|
||||||
</div>
|
</div>
|
||||||
<Info className={styles.infoarea} info={info} router={router} />
|
<Info className={styles.infoarea} info={info} />
|
||||||
<MoreLikeThis className={styles.related} data={data.moreLikeThis} />
|
<MoreLikeThis className={styles.related} data={data.moreLikeThis} />
|
||||||
</Layout>
|
</Layout>
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
// TO-DO: make a getServerSideProps wrapper for handling errors
|
// TO-DO: make a getServerSideProps wrapper for handling errors
|
||||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user