Просмотр исходного кода

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
zyachel 2 лет назад
Родитель
Сommit
57b050f196

+ 7 - 5
.prettierrc

@@ -1,6 +1,8 @@
 {
-    "trailingComma": "es5",
-    "tabWidth": 2,
-    "semi": false,
-    "singleQuote": true
-}
+  "trailingComma": "es5",
+  "tabWidth": 2,
+  "arrowParens": "avoid",
+  "semi": true,
+  "singleQuote": true,
+  "jsxSingleQuote": true
+}

+ 1 - 1
src/components/buttons/ThemeToggler.tsx

@@ -17,9 +17,9 @@ const ThemeToggler = (props: Props) => {
   return (
     <button
       className={`${styles.button}  ${props.className}`}
-      aria-label='Change theme'
       onClick={clickHandler}
     >
+      <span className='visually-hidden'>Change theme</span>
       <svg
         className={`icon ${styles.icon}`}
         focusable='false'

+ 10 - 10
src/components/Error/ErrorInfo.tsx → src/components/error/ErrorInfo.tsx

@@ -1,6 +1,6 @@
 import Link from 'next/link';
 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';
 
@@ -13,22 +13,22 @@ const ErrorInfo = ({ message = 'Not found, sorry.', statusCode = 404 }) => {
     <>
       <Meta
         title={`${message} (${statusCode})`}
-        description='you encountered an error page!'
+        description="you encountered an error page!"
       />
       <Layout className={styles.error}>
         <svg
           className={styles.gnu}
-          focusable='false'
-          role='img'
-          aria-labelledby='gnu-title gnu-desc'
+          focusable="false"
+          role="img"
+          aria-labelledby="gnu-title gnu-desc"
         >
-          <title id='gnu-title'>GNU and Tux</title>
-          <desc id='gnu-desc'>
+          <title id="gnu-title">GNU and Tux</title>
+          <desc id="gnu-desc">
             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,
             looking down and patting him on the back.
           </desc>
-          <use href='/svg/sadgnu.svg#sad-gnu'></use>
+          <use href="/svg/sadgnu.svg#sad-gnu"></use>
         </svg>
         <h1 className={`heading heading__primary ${styles.heading}`}>
           <span>{message}</span>
@@ -36,8 +36,8 @@ const ErrorInfo = ({ message = 'Not found, sorry.', statusCode = 404 }) => {
         </h1>
         <p className={styles.back}>
           Go back to{' '}
-          <Link href='/about'>
-            <a className='link'>the homepage</a>
+          <Link href="/about">
+            <a className="link">the homepage</a>
           </Link>
           .
         </p>

+ 0 - 0
src/components/Meta/Meta.tsx → src/components/meta/Meta.tsx


+ 21 - 21
src/components/title/Basic.tsx

@@ -1,27 +1,27 @@
-import { Fragment } from 'react'
-import Image from 'next/future/image'
-import Link from 'next/link'
+import { Fragment } from 'react';
+import Image from 'next/future/image';
+import Link from 'next/link';
 
 import {
   formatNumber,
   formatTime,
   getProxiedIMDbImgUrl,
   modifyIMDbImg,
-} from '../../utils/helpers'
-import { Basic } from '../../interfaces/shared/title'
-import styles from '../../styles/modules/components/title/basic.module.scss'
+} from '../../utils/helpers';
+import { Basic } from '../../interfaces/shared/title';
+import styles from '../../styles/modules/components/title/basic.module.scss';
 
 type Props = {
-  className: string
-  data: Basic
-}
+  className: string;
+  data: Basic;
+};
 
 const Basic = ({ data, className }: Props) => {
-  const titleType = data.type.id
+  const titleType = data.type.id;
   const releaseTime =
     titleType === 'tvSeries'
       ? `${data.releaseYear?.start}-${data.releaseYear?.end || 'present'}`
-      : data.releaseYear?.start
+      : data.releaseYear?.start;
 
   return (
     <section
@@ -45,11 +45,11 @@ const Basic = ({ data, className }: Props) => {
             alt={data.poster.caption}
             priority
             fill
-            sizes="300px"
+            sizes='300px'
           />
         ) : (
           <svg className={styles.image__NA}>
-            <use href="/svg/sprite.svg#icon-image-slash" />
+            <use href='/svg/sprite.svg#icon-image-slash' />
           </svg>
         )}
       </div>
@@ -57,7 +57,7 @@ const Basic = ({ data, className }: Props) => {
         <h1 className={`${styles.title} heading heading__primary`}>
           {data.title}
         </h1>
-        <ul className={styles.meta} aria-label="quick facts">
+        <ul className={styles.meta} aria-label='quick facts'>
           {data.status && data.status.id !== 'released' && (
             <li className={styles.meta__text}>{data.status.text}</li>
           )}
@@ -78,7 +78,7 @@ const Basic = ({ data, className }: Props) => {
               <p className={styles.rating}>
                 <span className={styles.rating__num}>{data.ratings.avg}</span>
                 <svg className={styles.rating__icon}>
-                  <use href="/svg/sprite.svg#icon-rating"></use>
+                  <use href='/svg/sprite.svg#icon-rating'></use>
                 </svg>
                 <span className={styles.rating__text}> Avg. rating</span>
               </p>
@@ -87,7 +87,7 @@ const Basic = ({ data, className }: Props) => {
                   {formatNumber(data.ratings.numVotes)}
                 </span>
                 <svg className={styles.rating__icon}>
-                  <use href="/svg/sprite.svg#icon-like-dislike"></use>
+                  <use href='/svg/sprite.svg#icon-like-dislike'></use>
                 </svg>
                 <span className={styles.rating__text}> No. of votes</span>
               </p>
@@ -99,7 +99,7 @@ const Basic = ({ data, className }: Props) => {
                 {formatNumber(data.ranking.position)}
               </span>
               <svg className={styles.rating__icon}>
-                <use href="/svg/sprite.svg#icon-graph-rising"></use>
+                <use href='/svg/sprite.svg#icon-graph-rising'></use>
               </svg>
               <span className={styles.rating__text}>
                 {' '}
@@ -136,7 +136,7 @@ const Basic = ({ data, className }: Props) => {
             <span className={styles.overview__text}>{data.plot || '-'}</span>
           </p>
         }
-        {data.primaryCrew.map((crewType) => (
+        {data.primaryCrew.map(crewType => (
           <p className={styles.crewType} key={crewType.type.id}>
             <span className={styles.crewType__heading}>
               {`${crewType.type.category}: `}
@@ -153,7 +153,7 @@ const Basic = ({ data, className }: Props) => {
         ))}
       </div>
     </section>
-  )
-}
+  );
+};
 
-export default Basic
+export default Basic;

+ 24 - 24
src/components/title/Info.tsx

@@ -1,5 +1,5 @@
 import Link from 'next/link';
-import { NextRouter } from 'next/router';
+import { useRouter } from 'next/router';
 import { Info } from '../../interfaces/shared/title';
 import { formatMoney, formatTime } from '../../utils/helpers';
 
@@ -8,10 +8,10 @@ import styles from '../../styles/modules/components/title/info.module.scss';
 type Props = {
   info: Info;
   className: string;
-  router: NextRouter;
 };
 
-const Info = ({ info, className, router }: Props) => {
+const Info = ({ info, className }: Props) => {
+  const router = useRouter();
   const { titleId } = router.query;
   const { boxOffice, details, meta, keywords, technicalSpecs, accolades } =
     info;
@@ -20,7 +20,7 @@ const Info = ({ info, className, router }: Props) => {
     <div className={`${className} ${styles.info}`}>
       {meta.infoEpisode && (
         <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}>
             {meta.infoEpisode.numSeason && (
               <p className={styles.series}>
@@ -50,14 +50,14 @@ const Info = ({ info, className, router }: Props) => {
             {meta.infoEpisode.prevId && (
               <p>
                 <Link href={`/title/${meta.infoEpisode.prevId}`}>
-                  <a className='link'>Go to previous episode</a>
+                  <a className="link">Go to previous episode</a>
                 </Link>
               </p>
             )}
             {meta.infoEpisode.nextId && (
               <p>
                 <Link href={`/title/${meta.infoEpisode.nextId}`}>
-                  <a className='link'>Go to next episode</a>
+                  <a className="link">Go to next episode</a>
                 </Link>
               </p>
             )}
@@ -66,7 +66,7 @@ const Info = ({ info, className, router }: Props) => {
       )}
       {meta.infoSeries && (
         <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}>
             <p>
               <span>Total Seasons: </span>
@@ -82,19 +82,19 @@ const Info = ({ info, className, router }: Props) => {
             </p>
             <p>
               <Link href={`/title/${titleId}/episodes`}>
-                <a className='link'>See all Episodes</a>
+                <a className="link">See all Episodes</a>
               </Link>
             </p>
           </div>
         </section>
       )}
       <section className={styles.accolades}>
-        <h2 className='heading heading__secondary'>Accolades</h2>
+        <h2 className="heading heading__secondary">Accolades</h2>
         <div className={styles.accolades__container}>
           {accolades.topRating && (
             <p>
               <Link href={`/chart/top`}>
-                <a className='link'>Top rated (#{accolades.topRating})</a>
+                <a className="link">Top rated (#{accolades.topRating})</a>
               </Link>
             </p>
           )}
@@ -112,21 +112,21 @@ const Info = ({ info, className, router }: Props) => {
           </p>
           <p>
             <Link href={`/title/${titleId}/awards`}>
-              <a className='link'>View all awards</a>
+              <a className="link">View all awards</a>
             </Link>
           </p>
         </div>
       </section>
       {!!keywords.total && (
         <section className={styles.keywords}>
-          <h2 className='heading heading__secondary'>Keywords</h2>
+          <h2 className="heading heading__secondary">Keywords</h2>
           <ul className={styles.keywords__container}>
             {keywords.list.map(word => (
               <li className={styles.keywords__item} key={word}>
                 <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>
               </li>
             ))}
@@ -135,7 +135,7 @@ const Info = ({ info, className, router }: Props) => {
       )}
       {!!Object.keys(details).length && (
         <section className={styles.details}>
-          <h2 className='heading heading__secondary'>Details</h2>
+          <h2 className="heading heading__secondary">Details</h2>
           <div className={styles.details__container}>
             {details.releaseDate && (
               <p>
@@ -156,7 +156,7 @@ const Info = ({ info, className, router }: Props) => {
                     <Link
                       href={`/search/title/?country_of_origin=${country.id}`}
                     >
-                      <a className='link'>{country.text}</a>
+                      <a className="link">{country.text}</a>
                     </Link>
                   </span>
                 ))}
@@ -168,7 +168,7 @@ const Info = ({ info, className, router }: Props) => {
                 {details.officialSites.sites.map((site, i) => (
                   <span key={site.url}>
                     {!!i && ', '}
-                    <a href={site.url} className='link'>
+                    <a href={site.url} className="link">
                       {site.name}
                     </a>
                   </span>
@@ -182,7 +182,7 @@ const Info = ({ info, className, router }: Props) => {
                   <span key={lang.id}>
                     {!!i && ', '}
                     <Link href={`/search/title/?primary_language=${lang.id}`}>
-                      <a className='link'>{lang.text}</a>
+                      <a className="link">{lang.text}</a>
                     </Link>
                   </span>
                 ))}
@@ -201,7 +201,7 @@ const Info = ({ info, className, router }: Props) => {
                   <span key={loc}>
                     {!!i && ', '}
                     <Link href={`/search/title/?locations=${loc}`}>
-                      <a className='link'>{loc}</a>
+                      <a className="link">{loc}</a>
                     </Link>
                   </span>
                 ))}
@@ -214,7 +214,7 @@ const Info = ({ info, className, router }: Props) => {
                   <span key={co.id}>
                     {!!i && ', '}
                     <Link href={`/company/${co.id}`}>
-                      <a className='link'>{co.name}</a>
+                      <a className="link">{co.name}</a>
                     </Link>
                   </span>
                 ))}
@@ -225,7 +225,7 @@ const Info = ({ info, className, router }: Props) => {
       )}
       {!!Object.keys(boxOffice).length && (
         <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}>
             {boxOffice.budget && (
               <p>
@@ -277,7 +277,7 @@ const Info = ({ info, className, router }: Props) => {
       )}
       {!!Object.keys(technicalSpecs).length && (
         <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}>
             {technicalSpecs.runtime && (
               <p>
@@ -293,7 +293,7 @@ const Info = ({ info, className, router }: Props) => {
                     <span key={color.id}>
                       {!!i && ', '}
                       <Link href={`/search/title/?colors=${color.id}`}>
-                        <a className='link'>{color.name}</a>
+                        <a className="link">{color.name}</a>
                       </Link>
                     </span>
                   ))}
@@ -308,7 +308,7 @@ const Info = ({ info, className, router }: Props) => {
                     <span key={sound.id}>
                       {!!i && ', '}
                       <Link href={`/search/title/?sound_mixes=${sound.id}`}>
-                        <a className='link'>{sound.name}</a>
+                        <a className="link">{sound.name}</a>
                       </Link>
                     </span>
                   ))}

+ 10 - 12
src/components/title/Media.tsx

@@ -1,6 +1,5 @@
 import Image from 'next/future/image';
 import Link from 'next/link';
-import { NextRouter } from 'next/router';
 import { Media } from '../../interfaces/shared/title';
 import { getProxiedIMDbImgUrl, modifyIMDbImg } from '../../utils/helpers';
 
@@ -9,21 +8,20 @@ import styles from '../../styles/modules/components/title/media.module.scss';
 type Props = {
   className: string;
   media: Media;
-  router: NextRouter;
 };
 
-const Media = ({ className, media, router }: Props) => {
+const Media = ({ className, media }: Props) => {
   return (
     <div className={`${className} ${styles.media}`}>
       {(media.trailer || !!media.videos.total) && (
         <section className={styles.videos}>
-          <h2 className="heading heading__secondary">Videos</h2>
+          <h2 className='heading heading__secondary'>Videos</h2>
 
           <div className={styles.videos__container}>
             {media.trailer && (
-              <div key={router.asPath} className={styles.trailer}>
+              <div className={styles.trailer}>
                 <video
-                  aria-label="trailer video"
+                  aria-label='trailer video'
                   // it's a relatively new tag. hence jsx-all1 complains
                   aria-description={media.trailer.caption}
                   controls
@@ -32,7 +30,7 @@ const Media = ({ className, media, router }: Props) => {
                     modifyIMDbImg(media.trailer.thumbnail)
                   )}
                   className={styles.trailer__video}
-                  preload="none"
+                  preload='none'
                 >
                   {media.trailer.urls.map(source => (
                     <source
@@ -53,9 +51,9 @@ const Media = ({ className, media, router }: Props) => {
                     <Image
                       className={styles.video__img}
                       src={modifyIMDbImg(video.thumbnail)}
-                      alt=""
+                      alt=''
                       fill
-                      sizes="400px"
+                      sizes='400px'
                     />
                     <p className={styles.video__caption}>
                       {video.caption} ({video.runtime}s)
@@ -68,16 +66,16 @@ const Media = ({ className, media, router }: Props) => {
       )}
       {!!media.images.total && (
         <section className={styles.images}>
-          <h2 className="heading heading__secondary">Images</h2>
+          <h2 className='heading heading__secondary'>Images</h2>
           <div className={styles.images__container}>
             {media.images.images.map(image => (
               <figure key={image.id} className={styles.image}>
                 <Image
                   className={styles.image__img}
                   src={modifyIMDbImg(image.url)}
-                  alt=""
+                  alt=''
                   fill
-                  sizes="400px"
+                  sizes='400px'
                 />
                 <figcaption className={styles.image__caption}>
                   {image.caption.plainText}

+ 8 - 8
src/components/title/Reviews.tsx

@@ -1,4 +1,4 @@
-import { NextRouter } from 'next/router';
+import { useRouter } from 'next/router';
 import Link from 'next/link';
 import { Reviews } from '../../interfaces/shared/title';
 import { formatNumber } from '../../utils/helpers';
@@ -6,15 +6,15 @@ import styles from '../../styles/modules/components/title/reviews.module.scss';
 
 type Props = {
   reviews: Reviews;
-  router: NextRouter;
 };
 
-const Reviews = ({ reviews, router }: Props) => {
+const Reviews = ({ reviews }: Props) => {
+  const router = useRouter();
   const { titleId } = router.query;
 
   return (
     <section className={styles.reviews}>
-      <h2 className='heading heading__secondary'>Reviews</h2>
+      <h2 className="heading heading__secondary">Reviews</h2>
 
       {reviews.featuredReview && (
         <article className={styles.reviews__reviewContainer}>
@@ -38,7 +38,7 @@ const Reviews = ({ reviews, router }: Props) => {
                 {' '}
                 by{' '}
                 <Link href={`/user/${reviews.featuredReview.reviewer.id}`}>
-                  <a className='link'>{reviews.featuredReview.reviewer.name}</a>
+                  <a className="link">{reviews.featuredReview.reviewer.name}</a>
                 </Link>
               </span>
               <span> on {reviews.featuredReview.date}.</span>
@@ -58,21 +58,21 @@ const Reviews = ({ reviews, router }: Props) => {
       <div className={styles.reviews__stats}>
         <p>
           <Link href={`/title/${titleId}/reviews`}>
-            <a className='link'>
+            <a className="link">
               {formatNumber(reviews.numUserReviews)} User reviews
             </a>
           </Link>
         </p>
         <p>
           <Link href={`/title/${titleId}/externalreviews`}>
-            <a className='link'>
+            <a className="link">
               {formatNumber(reviews.numCriticReviews)} Critic reviews
             </a>
           </Link>
         </p>
         <p>
           <Link href={`/title/${titleId}/criticreviews`}>
-            <a className='link'> {reviews.metacriticScore} Metascore</a>
+            <a className="link"> {reviews.metacriticScore} Metascore</a>
           </Link>
         </p>
       </div>

+ 9 - 0
src/components/title/index.tsx

@@ -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 - 0
src/hooks/usePageLoading.ts

@@ -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 - 1
src/pages/404.tsx

@@ -1,4 +1,4 @@
-import ErrorInfo from '../components/Error/ErrorInfo';
+import ErrorInfo from '../components/error/ErrorInfo';
 
 const Error404 = () => {
   return <ErrorInfo />;

+ 2 - 2
src/pages/500.tsx

@@ -1,6 +1,6 @@
-import ErrorInfo from '../components/Error/ErrorInfo';
+import ErrorInfo from '../components/error/ErrorInfo';
 
 const Error500 = () => {
-  return <ErrorInfo message='server messed up, sorry.' statusCode={500} />;
+  return <ErrorInfo message="server messed up, sorry." statusCode={500} />;
 };
 export default Error500;

+ 8 - 25
src/pages/_app.tsx

@@ -1,38 +1,21 @@
-import { useCallback, useEffect, useState } from 'react';
 import type { AppProps } from 'next/app';
-import { useRouter } from 'next/router';
-
+import usePageLoading from '../hooks/usePageLoading';
 import ProgressBar from '../components/loaders/ProgressBar';
 import ThemeProvider from '../context/theme-context';
 
 import '../styles/main.scss';
+import { useRouter } from 'next/router';
 
 const ModifiedApp = ({ Component, pageProps }: AppProps) => {
-  // for showing progress bar
-  // 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]);
-  //
+  const { isPageLoading, key } = usePageLoading();
 
   return (
     <ThemeProvider>
-      {isLoading && <ProgressBar />}
-      <Component {...pageProps} />
+      {isPageLoading && <ProgressBar />}
+      <Component
+        {...pageProps}
+        key={key} /* passing key to force react to remound components */
+      />
     </ThemeProvider>
   );
 };

+ 10 - 8
src/pages/_document.tsx

@@ -3,15 +3,17 @@ import Document, { Html, Head, Main, NextScript } from 'next/document';
 // 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/)
 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 browserPrefersDarkTheme = window.matchMedia(
-    '(prefers-color-scheme: dark)'
-  ).matches;
-  if (userPrefersTheme) return userPrefersTheme;
-  else if (browserPrefersDarkTheme) return 'dark';
-  else return 'light';
+  const browserPrefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches;
+  if (userPrefersTheme) theme = userPrefersTheme;
+  else if (browserPrefersDarkTheme) theme = 'dark';
+  if(theme === 'dark') themeColor = '#141c2e';
+  document.documentElement.dataset.theme  = theme;
+  document.querySelector('meta[name="theme-color"]').setAttribute('content', themeColor);
 })();
 `;
 

+ 43 - 49
src/pages/about/index.tsx

@@ -1,19 +1,19 @@
 /* eslint-disable react/no-unescaped-entities */
-import Link from 'next/link'
-import Meta from '../../components/Meta/Meta'
-import Layout from '../../layouts/Layout'
+import Link from 'next/link';
+import Meta from '../../components/meta/Meta';
+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 = () => {
   return (
     <>
       <Meta
-        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."
+        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.'
       />
       <Layout full className={styles.about}>
-        <section id="features" className={styles.features}>
+        <section id='features' className={styles.features}>
           <h2
             className={`heading heading__secondary ${styles.features__heading}`}
           >
@@ -22,12 +22,12 @@ const About = () => {
           <ul className={styles.features__list}>
             <li className={styles.feature}>
               <svg
-                aria-hidden="true"
-                focusable="false"
-                role="img"
+                aria-hidden='true'
+                focusable='false'
+                role='img'
                 className={styles.feature__icon}
               >
-                <use href="/svg/sprite.svg#icon-eye-slash"></use>
+                <use href='/svg/sprite.svg#icon-eye-slash'></use>
               </svg>
               <h3
                 className={`heading heading__tertiary ${styles.feature__heading}`}
@@ -41,12 +41,12 @@ const About = () => {
             </li>
             <li className={styles.feature}>
               <svg
-                aria-hidden="true"
-                focusable="false"
-                role="img"
+                aria-hidden='true'
+                focusable='false'
+                role='img'
                 className={styles.feature__icon}
               >
-                <use href="/svg/sprite.svg#icon-palette"></use>
+                <use href='/svg/sprite.svg#icon-palette'></use>
               </svg>
               <h3
                 className={`heading heading__tertiary ${styles.feature__heading}`}
@@ -60,12 +60,12 @@ const About = () => {
             </li>
             <li className={styles.feature}>
               <svg
-                aria-hidden="true"
-                focusable="false"
-                role="img"
+                aria-hidden='true'
+                focusable='false'
+                role='img'
                 className={styles.feature__icon}
               >
-                <use href="/svg/sprite.svg#icon-responsive"></use>
+                <use href='/svg/sprite.svg#icon-responsive'></use>
               </svg>
               <h3
                 className={`heading heading__tertiary ${styles.feature__heading}`}
@@ -79,7 +79,7 @@ const About = () => {
             </li>
           </ul>
         </section>
-        <section id="faq" className={styles.faqs}>
+        <section id='faq' className={styles.faqs}>
           <h2 className={`heading heading__secondary ${styles.faqs__heading}`}>
             Questions you may have
           </h2>
@@ -91,21 +91,25 @@ const About = () => {
               <p className={styles.faq__description}>
                 Replace `imdb.com` in any IMDb URL with any of the instances.
                 For example: `
-                <a href="https://imdb.com/title/tt1049413" className="link">
-                  imdb.com/title/tt1049413
-                </a>
-                ` to `
                 <a
-                  href="https://libremdb.iket.me/title/tt1049413"
-                  className="link"
+                  href='https://imdb.com/title/tt1049413'
+                  className='link'
+                  target='_blank'
+                  rel='noreferrer'
                 >
-                  libremdb.iket.me/title/tt1049413
+                  imdb.com/title/tt1049413
                 </a>
+                ` to `
+                <Link href='/title/tt1049413'>
+                  <a className='link'>
+                    {process.env.NEXT_PUBLIC_URL || ''}/title/tt1049413
+                  </a>
+                </Link>
                 ` . To avoid changing the URLs manually, you can use extensions
                 like{' '}
                 <a
-                  href="https://github.com/libredirect/libredirect/"
-                  className="link"
+                  href='https://github.com/libredirect/libredirect/'
+                  className='link'
                 >
                   LibRedirect
                 </a>
@@ -140,33 +144,23 @@ const About = () => {
                 instance to avoid exposing your IP address, browser information
                 and other personally identifiable metadata (
                 <a
-                  href="https://github.com/httpjamesm"
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  className="link"
+                  href='https://github.com/httpjamesm'
+                  target='_blank'
+                  rel='noopener noreferrer'
+                  className='link'
                 >
                   Contributor
                 </a>
                 ).
               </p>
             </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}>
               <summary className={styles.faq__summary}>
                 Why not just use IMDb?
               </summary>
               <p className={styles.faq__description}>
                 Refer to the{' '}
-                <a className="link" href="#features">
+                <a className='link' href='#features'>
                   features section
                 </a>{' '}
                 above.
@@ -196,8 +190,8 @@ const About = () => {
               </summary>
               <p className={styles.faq__description}>
                 That's great! I've a couple of{' '}
-                <Link href="/contact">
-                  <a className="link">contact methods</a>
+                <Link href='/contact'>
+                  <a className='link'>contact methods</a>
                 </Link>
                 . Send your beautiful suggestions(or complaints), or just drop a
                 hi.
@@ -207,7 +201,7 @@ const About = () => {
         </section>
       </Layout>
     </>
-  )
-}
+  );
+};
 
-export default About
+export default About;

+ 8 - 8
src/pages/contact/index.tsx

@@ -1,4 +1,4 @@
-import Meta from '../../components/Meta/Meta';
+import Meta from '../../components/meta/Meta';
 import Layout from '../../layouts/Layout';
 
 import styles from '../../styles/modules/pages/contact/contact.module.scss';
@@ -7,10 +7,10 @@ const Contact = () => {
   return (
     <>
       <Meta
-        title='Contact'
-        description='Contact page of libremdb, a free & open source IMDb front-end.'
+        title="Contact"
+        description="Contact page of libremdb, a free & open source IMDb front-end."
       />
-      <Layout className=''>
+      <Layout className="">
         <section className={styles.contact}>
           <h1 className={`heading heading__primary ${styles.contact__heading}`}>
             Contact
@@ -19,22 +19,22 @@ const Contact = () => {
           <div className={styles.list}>
             <p className={styles.item}>
               You can use{' '}
-              <a href='https://github.com/zyachel/libremdb' className='link'>
+              <a href="https://github.com/zyachel/libremdb" className="link">
                 GitHub
               </a>{' '}
               or{' '}
-              <a href='https://codeberg.org/zyachel/libremdb' className='link'>
+              <a href="https://codeberg.org/zyachel/libremdb" className="link">
                 Codeberg
               </a>{' '}
               for general issues, questions, or requests.
             </p>
             <p className={styles.item}>
               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]
               </a>{' '}
               and{' '}
-              <a className='link' href='mailto:aricla@protonmail.com'>
+              <a className="link" href="mailto:aricla@protonmail.com">
                 email
               </a>
               .

+ 6 - 6
src/pages/privacy/index.tsx

@@ -1,7 +1,7 @@
-import Meta from '../../components/Meta/Meta'
-import Layout from '../../layouts/Layout'
+import Meta from '../../components/meta/Meta';
+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 = () => {
   return (
@@ -55,7 +55,7 @@ const Privacy = () => {
         </section>
       </Layout>
     </>
-  )
-}
+  );
+};
 
-export default Privacy
+export default Privacy;

+ 27 - 28
src/pages/title/[titleId]/index.tsx

@@ -1,35 +1,34 @@
 // external
 import { GetServerSideProps, GetStaticProps, GetStaticPaths } from 'next'
-import { useRouter } from 'next/router'
+import Head from 'next/head';
+import { useRouter } from 'next/router';
 // local
-import Meta from '../../../components/Meta/Meta'
-import Layout from '../../../layouts/Layout'
-import title from '../../../utils/fetchers/title'
-// components
-import ErrorInfo from '../../../components/Error/ErrorInfo'
-import Basic from '../../../components/title/Basic'
-import Media from '../../../components/title/Media'
-import Cast from '../../../components/title/Cast'
-import DidYouKnow from '../../../components/title/DidYouKnow'
-import Info from '../../../components/title/Info'
-import Reviews from '../../../components/title/Reviews'
-import MoreLikeThis from '../../../components/title/MoreLikeThis'
+import Meta from '../../../components/meta/Meta';
+import Layout from '../../../layouts/Layout';
+import ErrorInfo from '../../../components/error/ErrorInfo';
+import {
+  Basic,
+  Cast,
+  DidYouKnow,
+  Info,
+  Media,
+  MoreLikeThis,
+  Reviews,
+} from '../../../components/title';
 // misc
-import Title from '../../../interfaces/shared/title'
-import { AppError } from '../../../interfaces/shared/error'
+import Title from '../../../interfaces/shared/title';
+import { AppError } from '../../../interfaces/shared/error';
+import title from '../../../utils/fetchers/title';
+import { getProxiedIMDbImgUrl } from '../../../utils/helpers';
 // styles
-import styles from '../../../styles/modules/pages/title/title.module.scss'
-import Head from 'next/head'
-import { getProxiedIMDbImgUrl } from '../../../utils/helpers'
+import styles from '../../../styles/modules/pages/title/title.module.scss';
 
-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
 const TitleInfo = ({ data, error }: Props) => {
-  const router = useRouter()
-
   if (error)
-    return <ErrorInfo message={error.message} statusCode={error.statusCode} />
+    return <ErrorInfo message={error.message} statusCode={error.statusCode} />;
 
   const info = {
     meta: data.meta,
@@ -38,7 +37,7 @@ const TitleInfo = ({ data, error }: Props) => {
     boxOffice: data.boxOffice,
     technicalSpecs: data.technicalSpecs,
     accolades: data.accolades,
-  }
+  };
 
   return (
     <>
@@ -60,18 +59,18 @@ const TitleInfo = ({ data, error }: Props) => {
       </Head>
       <Layout className={styles.title}>
         <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} />
         <div className={styles.textarea}>
           <DidYouKnow data={data.didYouKnow} />
-          <Reviews reviews={data.reviews} router={router} />
+          <Reviews reviews={data.reviews} />
         </div>
-        <Info className={styles.infoarea} info={info} router={router} />
+        <Info className={styles.infoarea} info={info} />
         <MoreLikeThis className={styles.related} data={data.moreLikeThis} />
       </Layout>
     </>
-  )
-}
+  );
+};
 
 // TO-DO: make a getServerSideProps wrapper for handling errors
 export const getServerSideProps: GetServerSideProps = async (ctx) => {