├── .all-contributorsrc ├── .babelrc ├── .env.example ├── .eslintignore ├── .eslintrc ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ └── feature_request.yml └── workflows │ └── trello.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .prettierignore ├── .prettierrc ├── .versionrc.json ├── .vscode ├── launch.json └── settings.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── components ├── AboutUserSection │ ├── AboutUserSection.tsx │ └── index.ts ├── ActiveHero │ ├── ActiveHero.tsx │ └── index.ts ├── AlertBanner │ ├── AlertBanner.tsx │ └── index.ts ├── AppLayout │ ├── AppLayout.tsx │ └── index.ts ├── BannedPage │ ├── BannedPage.tsx │ └── index.ts ├── Card │ ├── Card.tsx │ └── index.ts ├── CardGrid │ ├── CardGrid.tsx │ └── index.ts ├── ErrorPage │ ├── ErrorPage.tsx │ └── index.ts ├── Footer │ ├── Footer.tsx │ └── index.ts ├── HomePage │ ├── HomePage.tsx │ └── index.ts ├── LandingPage │ ├── LandingPage.tsx │ └── index.ts ├── MovieDetailsSection │ ├── MovieDetailsSection.tsx │ └── index.ts ├── MovieGridView │ ├── MovieGridView.tsx │ └── index.ts ├── MovieModal │ ├── MovieModal.tsx │ └── index.ts ├── MovieReviewSection │ ├── MovieReviewSection.tsx │ └── index.tsx ├── Nav │ ├── Nav.test.tsx │ ├── Nav.tsx │ └── index.ts ├── Rating │ ├── Rating.test.tsx │ ├── Rating.test.tsx.snap │ ├── Rating.tsx │ └── index.ts ├── ReviewModal │ ├── ReviewModal.tsx │ └── index.ts ├── SearchResults │ ├── SearchResults.tsx │ └── index.ts ├── UserReviewSection │ ├── UserReviewSection.tsx │ └── index.ts ├── UserTable │ ├── UserTable.tsx │ └── index.ts └── Wave │ ├── Wave.tsx │ └── index.tsx ├── cypress.json ├── cypress ├── .eslintrc.json ├── fixtures │ └── example.json ├── integration │ └── setup.js ├── plugins │ └── index.js └── support │ ├── commands.js │ └── index.js ├── hooks └── useScrollPosition.hook.tsx ├── jest.config.js ├── jest.snapshot-resolver.js ├── models ├── index.ts ├── movie.ts ├── user.ts └── userAuthModel.ts ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages ├── 404.tsx ├── _app.tsx ├── _document.tsx ├── _error.tsx ├── api │ ├── auth │ │ └── [...nextauth].ts │ ├── movie-api.ts │ ├── movie.ts │ ├── movie │ │ └── [id].ts │ ├── review.ts │ ├── user │ │ ├── [userID].ts │ │ └── index.ts │ └── users.ts ├── index.tsx ├── movie │ └── [id].tsx ├── user │ └── [uID].tsx └── users.tsx ├── public ├── favicon.ico ├── sitePicture.jpg └── vercel.svg ├── styles ├── Home.module.css ├── component_styles │ ├── Button.ts │ ├── Switch.ts │ └── index.ts ├── globals.css └── theme.ts ├── tsconfig.jest.json ├── tsconfig.json ├── types ├── APITypes.ts ├── generalTypes.ts └── next-auth.d.ts ├── utils ├── ModalContext.ts ├── dbConnect.ts ├── myAdapter.ts ├── queries.ts ├── userFlags.ts └── utils.ts └── vercel.json /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "badgeTemplate": "\n\"contributors\"-orange.svg?style=for-the-badge&color=%23F6E05E\" />", 7 | "commit": true, 8 | "contributors": [ 9 | { 10 | "login": "mah51", 11 | "name": "Michael Hall", 12 | "avatar_url": "https://avatars.githubusercontent.com/u/47287285?v=4", 13 | "profile": "https://www.mikeroph.one/", 14 | "contributions": [ 15 | "code", 16 | "content", 17 | "doc", 18 | "design", 19 | "maintenance", 20 | "review" 21 | ] 22 | }, 23 | { 24 | "login": "olig89", 25 | "name": "Oli Gill", 26 | "avatar_url": "https://avatars.githubusercontent.com/u/24813487?v=4", 27 | "profile": "http://olivergill.com", 28 | "contributions": [ 29 | "bug", 30 | "ideas", 31 | "test" 32 | ] 33 | } 34 | ], 35 | "contributorsPerLine": 7, 36 | "projectName": "ScuffedMDB", 37 | "projectOwner": "mah51", 38 | "repoType": "github", 39 | "repoHost": "https://github.com", 40 | "skipCi": true 41 | } 42 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"] 3 | } 4 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ### REQUIRED INPUTS ### 2 | NEXT_PUBLIC_APP_URI= 3 | 4 | OWNER_ID= 5 | CLIENT_ID= 6 | CLIENT_SECRET= 7 | 8 | JWT_CODE= 9 | 10 | MONGODB_URI= 11 | 12 | JWT_HS512={"kty":"oct","kid":"-token-","alg":"HS512","k":"-token-"} 13 | 14 | MOVIE_API_KEY= 15 | 16 | #AUTH ENDPOINT - Set by default 17 | 18 | NEXTAUTH_URL=${NEXT_PUBLIC_APP_URI}/api/auth 19 | 20 | ### ALLOWED USERS - Limit only certain discord users to log in### 21 | 22 | #ALLOWED_USERS= 23 | 24 | ### DISCORD BOT ### 25 | 26 | # Only uncomment these if you want to use the bot at https://github.com/mah51/scuffedmdb-bot 27 | # WEBHOOK_URL= 28 | # WEBHOOK_TOKEN= 29 | 30 | #### CUSTOMISATIONS 31 | 32 | # Uncomment to set the name of the webapp 33 | # NEXT_PUBLIC_SITE_NAME= 34 | # NEXT_PUBLIC_SHORT_SITE_NAME= 35 | 36 | # COLOR_THEME=purple 37 | # purple (default) | red | orange | yellow | green | teal | blue | cyan | pink | gray 38 | # SECONDARY_COLOR_THEME = ./utils/utils has default pairs of colours but if you want to customise yours, use this option. 39 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules/* 2 | **/out/* 3 | **/.next/* -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | 4 | "plugins": ["@typescript-eslint"], 5 | 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:react/recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "next", 11 | 12 | // Uncomment the following lines to enable eslint-config-prettier 13 | // Is not enabled right now to avoid issues with the Next.js repo 14 | "prettier" 15 | ], 16 | 17 | "env": { 18 | "es6": true, 19 | "browser": true, 20 | "jest": true, 21 | "node": true 22 | }, 23 | 24 | "settings": { 25 | "react": { 26 | "version": "detect" 27 | } 28 | }, 29 | 30 | "rules": { 31 | "no-case-declarations": "off", 32 | "@typescript-eslint/ban-ts-comment": "off", 33 | "react/react-in-jsx-scope": 0, 34 | "react/display-name": 0, 35 | "react/prop-types": 0, 36 | "@typescript-eslint/explicit-function-return-type": 0, 37 | "@typescript-eslint/explicit-member-accessibility": 0, 38 | "@typescript-eslint/indent": 0, 39 | "@typescript-eslint/member-delimiter-style": 0, 40 | "@typescript-eslint/no-explicit-any": 0, 41 | "@typescript-eslint/no-var-requires": 0, 42 | "@typescript-eslint/no-use-before-define": 0, 43 | "@typescript-eslint/no-unused-vars": [ 44 | 2, 45 | { 46 | "argsIgnorePattern": "^_" 47 | } 48 | ], 49 | "no-console": [ 50 | 2, 51 | { 52 | "allow": ["warn", "error"] 53 | } 54 | ] 55 | }, 56 | 57 | "overrides": [ 58 | { 59 | "files": ["*.test.js*"], 60 | 61 | "env": { 62 | "jest": true 63 | }, 64 | 65 | "rules": { 66 | "jest/no-disabled-tests": "error", 67 | "jest/no-focused-tests": "error", 68 | "jest/no-identical-title": "error", 69 | "jest/no-jest-import": "error", 70 | "jest/no-test-return-statement": "error", 71 | "jest/prefer-to-be-null": "warn", 72 | "jest/prefer-to-be-undefined": "warn", 73 | "jest/prefer-to-have-length": "warn", 74 | "jest/valid-describe": "error", 75 | "jest/valid-expect": "error" 76 | } 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 'Bug Report' 2 | description: 'File a bug report' 3 | labels: ['bug'] 4 | body: 5 | - type: 'markdown' 6 | attributes: 7 | value: | 8 | Thanks for creating an issue 😄! 9 | - type: 'textarea' 10 | id: 'description' 11 | attributes: 12 | label: 'Description' 13 | description: 'A brief description of the issue.' 14 | placeholder: | 15 | When I ____, I expected ____ to happen but ____ happened instead. 16 | validations: 17 | required: true 18 | - type: 'input' 19 | id: 'reproduction' 20 | attributes: 21 | label: 'Link to Reproduction' 22 | description: | 23 | A link to your repo, or the website. 24 | placeholder: 'https://movie.mikeroph.one' 25 | validations: 26 | required: false 27 | - type: 'textarea' 28 | id: 'steps' 29 | attributes: 30 | label: 'Steps to reproduce' 31 | description: | 32 | Explain how to cause the issue in the provided reproduction. 33 | value: | 34 | 1. Go to '...' 35 | 2. Click on '...' 36 | 3. Scroll down to '...' 37 | 4. See error 38 | - type: 'input' 39 | id: 'browser' 40 | attributes: 41 | label: 'Browser' 42 | description: 'The browser(s) this issue occurred with. (if relevant - styling issues etc)' 43 | placeholder: 'Google Chrome 93' 44 | - type: 'checkboxes' 45 | id: 'operating-system' 46 | attributes: 47 | label: 'Operating System' 48 | description: 'The operating system(s) this issue occurred with.' 49 | options: 50 | - label: 'macOS' 51 | - label: 'Windows' 52 | - label: 'Linux' 53 | - label: 'IOS / Android' 54 | - type: 'textarea' 55 | id: 'additional-information' 56 | attributes: 57 | label: 'Additional Information' 58 | description: | 59 | Use this section to provide any additional information you might have 60 | like screenshots, notes, or links to ideas. 61 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "Feature Request" 2 | description: "Request a feature or enhancement" 3 | labels: ["feature request"] 4 | body: 5 | - type: "markdown" 6 | attributes: 7 | value: | 8 | Thank you for creating a feature request 🥳! 9 | - type: "textarea" 10 | id: "description" 11 | attributes: 12 | label: "Description" 13 | description: "Please describe your request in one or two sentences." 14 | validations: 15 | required: true 16 | - type: "dropdown" 17 | id: "identification" 18 | attributes: 19 | label: In relation to... 20 | description: What part of the codebase are you having an issue with? 21 | options: 22 | - API route (/pages/api/*) 23 | - A page route (/pages/*) 24 | - A component 25 | - Styling 26 | - Vercel 27 | - Other 28 | validations: 29 | required: true 30 | - type: "textarea" 31 | id: "justification" 32 | attributes: 33 | label: "Justification" 34 | description: | 35 | Please provide valid reason(s) why this should be added the website 36 | validations: 37 | required: true 38 | - type: "textarea" 39 | id: "proposed-solution" 40 | attributes: 41 | label: "Proposed Solution" 42 | description: | 43 | If you have any thoughts on how to implement this idea, please note them down! 44 | validations: 45 | required: false 46 | - type: "textarea" 47 | id: "additional-information" 48 | attributes: 49 | label: "Additional Information" 50 | description: | 51 | Additional resources (links, screenshots, etc.). 52 | 53 | -------------------------------------------------------------------------------- /.github/workflows/trello.yml: -------------------------------------------------------------------------------- 1 | name: Trello Issue List 2 | on: 3 | issues: 4 | types: [opened] 5 | env: 6 | TRELLO_KEY: ${{ secrets.TRELLO_KEY }} 7 | TRELLO_TOKEN: ${{ secrets.TRELLO_TOKEN }} 8 | 9 | jobs: 10 | issue_send: 11 | name: Send Issue to Trello 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Runs trello manage 15 | uses: sisodiya2421/trello-manage@master 16 | with: 17 | repo-name: ${{ github.repository }} 18 | trello-username: ${{ secrets.TRELLO_USERNAME }} 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | 14 | *.snap 15 | /out/ 16 | 17 | # production 18 | /build 19 | 20 | # misc 21 | .DS_Store 22 | *.pem 23 | 24 | # debug 25 | npm-debug.log* 26 | yarn-debug.log* 27 | yarn-error.log* 28 | 29 | # local env files 30 | .env.local 31 | .env.development.local 32 | .env.test.local 33 | .env.production.local 34 | 35 | # vercel 36 | .vercel 37 | dump 38 | cypress.env.json 39 | screenshotsFolder 40 | videosFolder -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run pre-commit 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .next 3 | yarn.lock 4 | package-lock.json 5 | public -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | { "type": "chore", "section": "Others", "hidden": false }, 4 | { "type": "revert", "section": "Reverts", "hidden": false }, 5 | { "type": "feat", "section": "Features", "hidden": false }, 6 | { "type": "fix", "section": "Bug Fixes", "hidden": false }, 7 | { 8 | "type": "improvement", 9 | "section": "Feature Improvements", 10 | "hidden": false 11 | }, 12 | { "type": "ui", "section": "User Interface", "hidden": false }, 13 | { "type": "ux", "section": "User Experience", "hidden": false }, 14 | { "type": "docs", "section": "Docs", "hidden": false }, 15 | { "type": "style", "section": "Styling", "hidden": false }, 16 | { "type": "refactor", "section": "Code Refactoring", "hidden": false }, 17 | { "type": "perf", "section": "Performance Improvements", "hidden": false }, 18 | { "type": "test", "section": "Tests", "hidden": false }, 19 | { "type": "build", "section": "Build System", "hidden": false }, 20 | { "type": "ci", "section": "CI", "hidden": false } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "attach", 7 | "name": "Launch Program", 8 | "skipFiles": ["/**"], 9 | "port": 9229 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["OMDB"] 3 | } 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How can you help out? 2 | 3 | Any contributions are welcome! These guidelines should help you get setup and developing :). 4 | 5 | To contribute, follow the [setting up local environment instructions](/README.md#setting-up-the-local-environment); 6 | 7 | When you make a commit please use `npx cz` in place of git commit, to keep inline with the cz standard. Pick the relevant type, for example if you are fixing a bug then (fix). When applying a scope i don't really stick to the convention, e.g. If I am working on the ReviewModal component I will use that as the scope. And please be relatively descriptive in your commits, as they will be included in the [changelog](/CHANGELOG.md). 8 | 9 | When you npm install a husky hook should install that checks your code for any typescript / eslint errors after the commit, if this fails and you need to re-commit, use `npx cz --retry`. 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Michael Hall 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/AboutUserSection/AboutUserSection.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Avatar, 4 | Flex, 5 | Heading, 6 | chakra, 7 | VStack, 8 | Text, 9 | useBreakpointValue, 10 | } from '@chakra-ui/react'; 11 | import { PopulatedUserType } from '../../models/user'; 12 | import { ReviewType } from '../../models/movie'; 13 | import { UserPageUser } from 'pages/user/[uID]'; 14 | 15 | interface AboutUserSectionProps { 16 | user: UserPageUser; 17 | reviews: ( 18 | | (ReviewType & { 19 | movie?: { name: string; image?: string }; 20 | }) 21 | | null 22 | )[]; 23 | } 24 | 25 | export const AboutUserSection: React.FC = ({ 26 | user, 27 | reviews, 28 | }): React.ReactElement => { 29 | return ( 30 | 35 | 40 | 44 | 45 | {user.username} 46 | 47 | #{user.discriminator} 48 | 49 | 50 | 55 | {reviews.length === 0 ? 'No reviews' : reviews.length + ' Rating'} 56 | {reviews.length > 1 ? 's' : ''}{' '} 57 | {reviews.length > 0 && 58 | '· ' + 59 | ( 60 | reviews.reduce((a, c) => (c?.rating ? a + c?.rating : a), 0) / 61 | reviews.length 62 | ).toFixed(1) + 63 | ' Average Rating'} 64 | 65 | 66 | 67 | ); 68 | }; 69 | -------------------------------------------------------------------------------- /components/AboutUserSection/index.ts: -------------------------------------------------------------------------------- 1 | export { AboutUserSection as default } from './AboutUserSection'; 2 | -------------------------------------------------------------------------------- /components/ActiveHero/ActiveHero.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | AspectRatio, 3 | Flex, 4 | Heading, 5 | Link as ChakraLink, 6 | Text, 7 | useColorMode, 8 | useToast, 9 | VStack, 10 | } from '@chakra-ui/react'; 11 | import { transparentize } from '@chakra-ui/theme-tools'; 12 | import { SerializedMovieType } from 'models/movie'; 13 | import { useSession } from 'next-auth/client'; 14 | import Image from 'next/image'; 15 | import Link from 'next/link'; 16 | import React, { useContext } from 'react'; 17 | import { ReactElement } from 'react'; 18 | import { ReviewModalContext } from 'utils/ModalContext'; 19 | 20 | interface Props { 21 | movie: SerializedMovieType | undefined; 22 | } 23 | 24 | export default function ActiveHero({ movie }: Props): ReactElement | null { 25 | const { colorMode } = useColorMode(); 26 | 27 | const [session] = useSession(); 28 | const toast = useToast(); 29 | 30 | const { onOpen, setMovie } = useContext(ReviewModalContext); 31 | const hasReviewed = movie?.reviews?.some( 32 | (m) => m?.user?._id === session?.user.sub 33 | ); 34 | if (!movie) return null; 35 | 36 | return ( 37 | 49 | 66 | Latest Movie 67 | 68 | 69 | 70 | 71 | {`${movie.name} 78 | 79 | 80 | 87 | {movie.name} 88 | {movie.tagLine} 89 | 90 | 91 | 102 | 103 | 117 | Details 118 | 119 | 120 | { 123 | if (session?.user?.isAdmin || session?.user?.isReviewer) { 124 | setMovie(movie); 125 | onOpen(); 126 | } else { 127 | return toast({ 128 | variant: `subtle`, 129 | title: `You can't add or remove reviews.`, 130 | description: `Contact the owner of the site to obtain the correct permissions.`, 131 | status: `error`, 132 | duration: 5000, 133 | isClosable: true, 134 | }); 135 | } 136 | }} 137 | color={`${process.env.COLOR_THEME}.${ 138 | colorMode === 'light' ? 500 : 300 139 | }`} 140 | _hover={{ 141 | bg: transparentize( 142 | `${process.env.COLOR_THEME}.${colorMode === 'light' ? 500 : 200}`, 143 | 0.16 144 | ), 145 | }} 146 | borderBottomRightRadius="2xl" 147 | width="50%" 148 | p={2} 149 | > 150 | {hasReviewed ? 'Edit review' : 'Add review'} 151 | 152 | 153 | 154 | ); 155 | } 156 | -------------------------------------------------------------------------------- /components/ActiveHero/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ActiveHero'; 2 | -------------------------------------------------------------------------------- /components/AlertBanner/AlertBanner.tsx: -------------------------------------------------------------------------------- 1 | import { CloseButton, Flex, Text, useColorModeValue } from '@chakra-ui/react'; 2 | import React, { ReactElement } from 'react'; 3 | import { useEffect } from 'react'; 4 | import { transparentize } from '@chakra-ui/theme-tools'; 5 | interface Props { 6 | message: string; 7 | title: string; 8 | storageName: string; 9 | color: string; 10 | } 11 | 12 | export default function AlertBanner({ 13 | message, 14 | title, 15 | color, 16 | storageName, 17 | }: Props): ReactElement { 18 | const [isOpen, setIsOpen] = React.useState(false); 19 | const bg = useColorModeValue( 20 | transparentize(`${color}.700`, 0.2), 21 | transparentize(`${color}.300`, 0.1) 22 | ); 23 | 24 | useEffect(() => { 25 | const cookie = window.localStorage.getItem(storageName); 26 | 27 | if (!cookie) { 28 | setIsOpen(true); 29 | } 30 | }, [storageName]); 31 | 32 | const handleDismiss = () => { 33 | setIsOpen(false); 34 | window.localStorage.setItem(storageName, 'true'); 35 | }; 36 | 37 | return ( 38 | 49 | 54 | {title} 55 | 56 | 57 | 62 | {message} 63 | 64 | 74 | 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /components/AlertBanner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AlertBanner'; 2 | -------------------------------------------------------------------------------- /components/AppLayout/AppLayout.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | import Nav from '../Nav'; 3 | import Footer from '../Footer'; 4 | import { UserAuthType } from 'next-auth'; 5 | import { Flex, useColorModeValue } from '@chakra-ui/react'; 6 | import theme from 'styles/theme'; 7 | import { css, Global } from '@emotion/react'; 8 | 9 | interface AppLayoutProps { 10 | user: UserAuthType; 11 | children: ReactNode; 12 | showMovies?: boolean; 13 | showReview?: boolean; 14 | } 15 | 16 | export const AppLayout = ({ 17 | showMovies, 18 | showReview, 19 | user, 20 | children, 21 | }: AppLayoutProps): React.ReactElement => ( 22 | 23 | 66 |