├── .gitignore ├── Documentation.md ├── Readme.md ├── index.html ├── markup ├── Readme.md ├── add-review.html ├── css │ ├── main.css │ └── main.min.css ├── head-guest.html ├── img │ ├── avatar.jpg │ ├── aviator.jpg │ ├── bg-header.jpg │ ├── bg-the-grand-budapest-hotel.jpg │ ├── bohemian-rhapsody.jpg │ ├── dardjeeling-limited.jpg │ ├── fantastic-beasts-the-crimes-of-grindelwald.jpg │ ├── icons │ │ ├── add.svg │ │ ├── full-screen.svg │ │ ├── in-list.svg │ │ ├── pause.svg │ │ └── play-s.svg │ ├── johnny-english.jpg │ ├── macbeth.jpg │ ├── midnight-special.jpg │ ├── mindhunter.jpg │ ├── moonrise-kingdom.jpg │ ├── no-country-for-old-men.jpg │ ├── orlando.jpg │ ├── player-poster.jpg │ ├── pulp-fiction.jpg │ ├── revenant.jpg │ ├── seven-years-in-tibet.jpg │ ├── shutter-island.jpg │ ├── snatch.jpg │ ├── the-grand-budapest-hotel-poster.jpg │ ├── war-of-the-worlds.jpg │ ├── we-need-to-talk-about-kevin.jpg │ └── what-we-do-in-the-shadows.jpg ├── main.html ├── movie-page-details.html ├── movie-page-in-list.html ├── movie-page-reviews.html ├── movie-page.html ├── my-list.html ├── player-pause.html ├── player.html ├── sign-in-error.html ├── sign-in-message.html └── sign-in.html ├── package-lock.json ├── package.json ├── public ├── 404.html ├── css │ ├── main.css │ └── main.min.css ├── favicon.ico ├── img │ ├── avatar.jpg │ ├── aviator.jpg │ ├── bg-header.jpg │ ├── bg-the-grand-budapest-hotel.jpg │ ├── bohemian-rhapsody.jpg │ ├── dardjeeling-limited.jpg │ ├── fantastic-beasts-the-crimes-of-grindelwald.jpg │ ├── favicons │ │ ├── 192.png │ │ ├── 512.png │ │ ├── apple.png │ │ └── icon.svg │ ├── icons │ │ ├── add.svg │ │ ├── full-screen.svg │ │ ├── in-list.svg │ │ ├── pause.svg │ │ └── play-s.svg │ ├── johnny-english.jpg │ ├── macbeth.jpg │ ├── midnight-special.jpg │ ├── mindhunter.jpg │ ├── moonrise-kingdom.jpg │ ├── no-country-for-old-men.jpg │ ├── orlando.jpg │ ├── player-poster.jpg │ ├── pulp-fiction.jpg │ ├── revenant.jpg │ ├── seven-years-in-tibet.jpg │ ├── shutter-island.jpg │ ├── snatch.jpg │ ├── the-grand-budapest-hotel-poster.jpg │ ├── war-of-the-worlds.jpg │ ├── we-need-to-talk-about-kevin.jpg │ └── what-we-do-in-the-shadows.jpg └── manifest.webmanifest ├── src ├── browser-history.ts ├── components │ ├── app │ │ └── app.tsx │ ├── buttons │ │ ├── my-list-button │ │ │ └── my-list-button.tsx │ │ ├── play-button │ │ │ └── play-button.tsx │ │ ├── review-button │ │ │ └── review-button.tsx │ │ └── show-more-button │ │ │ └── show-more-button.tsx │ ├── catalog │ │ └── catalog.tsx │ ├── film-card-full │ │ └── film-card-full.tsx │ ├── film-card-promo │ │ └── film-card-promo.tsx │ ├── film-card-small │ │ └── film-card-small.tsx │ ├── film-card-video-player │ │ └── film-card-video-player.tsx │ ├── film-cards-list │ │ └── film-cards-list.tsx │ ├── filter-genre │ │ └── filter-genre.tsx │ ├── footer │ │ └── footer.tsx │ ├── header │ │ └── header.tsx │ ├── history-route │ │ └── history-route.tsx │ ├── loader │ │ ├── loader.css │ │ └── loader.tsx │ ├── login-form │ │ └── login-form.tsx │ ├── logo │ │ └── logo.tsx │ ├── private-route │ │ └── private-route.tsx │ ├── review-form │ │ └── review-form.tsx │ ├── review │ │ └── review.tsx │ ├── tabs │ │ ├── tab-details │ │ │ └── tab-details.tsx │ │ ├── tab-overview │ │ │ └── tab-overview.tsx │ │ ├── tab-reviews │ │ │ └── tab-reviews.tsx │ │ ├── tabs-navigation │ │ │ └── tabs-navigation.tsx │ │ └── tabs │ │ │ └── tabs.tsx │ └── user-header │ │ ├── user-header-auth.tsx │ │ └── user-header-not-auth.tsx ├── const.ts ├── hooks │ └── index.ts ├── index.tsx ├── pages │ ├── add-review │ │ └── add-review.tsx │ ├── film │ │ └── film.tsx │ ├── login │ │ └── login.tsx │ ├── main │ │ └── main.tsx │ ├── my-list │ │ └── my-list.tsx │ ├── page-not-found │ │ └── page-not-found.tsx │ └── player │ │ └── player.tsx ├── services │ ├── api.ts │ └── token.ts ├── setupTests.ts ├── store │ ├── api-actions.ts │ ├── films-data │ │ ├── films-data-selectors.ts │ │ └── fims-data.slice.ts │ ├── index.ts │ ├── main-process │ │ ├── main-process.selectors.ts │ │ └── main-process.slice.ts │ ├── root-reducer.ts │ └── user-process │ │ ├── user-process.selectors.ts │ │ └── user-process.slice.ts ├── types │ ├── auth-data.ts │ ├── film.ts │ ├── films.ts │ ├── my-list.ts │ ├── reviews.ts │ ├── state.ts │ └── user.ts └── utils.ts ├── tsconfig.json ├── tsconfig.node.json ├── vercel.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /Documentation.md: -------------------------------------------------------------------------------- 1 | ## 1. Description of functionality 2 | 3 | ### 1.1. Application pages 4 | 5 | The application consists of several pages: Main (/), Sign In (/login), MyList (/mylist), Film (/films/:id), Add review (/films/:id/review), Player (/player/ :id). 6 | 7 | The MyList and Add review pages are available only to authorized users. If the user is not authorized, then when navigating to these pages, they are redirected to the Sign In page. 8 | 9 | If the user is not authorized, then when they try to go to a private page, they are redirected to the “Sign In” page (/login). 10 | 11 | In the right corner of the header, the user’s avatar and the “Sign Out” button (if the user is authorized) or the “Sign In” link (if the user is not authorized) are displayed. 12 | 13 | Clicking on the “Sign Out” button ends the work session - exiting the closed part of the application. 14 | 15 | Clicking on the user's avatar takes you to the MyList page (/mylist). 16 | 17 | Accessing a non-existent page (for example, through the address bar) does not lead to errors in the application, but is correctly processed by routing. The user is redirected to a “404” page. Page design is at the discretion of the student. In the simplest case, this could be a page with the text 404 Not Found and a link to go to the main page of the application. 18 | 19 | #### 1.1.1. Main page 20 | 21 | The main page presents genres and movie previews. 22 | 23 | A page with a detailed description of the film is available to all users. 24 | 25 | The page header displays the poster and cover of the promotional film. 26 | 27 | The promotional film can be watched immediately by clicking the “Play” button or added to the “My List”. 28 | 29 | Receiving a promotional film for the main page is performed by a separate request to the server (see “Routes”). 30 | 31 | After downloading the application, 8 movie cards of arbitrary genres are displayed. “All genres” is highlighted in the list of genres. 32 | 33 | The list of genres is built based on information about films received from the server. 34 | 35 | The list of genres displays no more than 9 genres + All genres (displays films of any genres in the list). 36 | 37 | #### 1.1.1.1. Movie list 38 | 39 | When changing the genre or receiving information about films from the server, no more than 8 films are displayed in the list of films. 40 | 41 | Showing additional films is done by clicking on the “Show more” button. 42 | 43 | Clicking on the “Show more” button adds the next 8 films to the list or the remaining films if there are fewer. 44 | 45 | After all movies corresponding to the selected genre are displayed, the “Show more” button is hidden. 46 | 47 | When you move from the main page to other pages of the application and back, the counter of the films shown is reset and the countdown begins again. 48 | 49 | #### 1.1.1.2. Movie card in movie list 50 | 51 | The movie card displays the following information: 52 | 53 | * Image (movie preview). 54 | * Movie title. 55 | * Clicking on the image or title of a movie takes you to the “Film” page (/films/:id). 56 | 57 | When you hover and hold the mouse cursor over a movie image, a video preview of the movie starts playing instead of the image. The video player is activated one second after hovering and holding the cursor on the card with the movie. 58 | 59 | The movie preview plays without sound. If the user moves the cursor from the card, playback stops and the card returns to its original state - instead of a video, a static image is displayed (as it was originally). When you hover over the card again, the preview playback starts again. 60 | 61 | #### 1.1.2. Movie description page 62 | 63 | A page with a detailed description of the film is available at /films/:id, where id is the film identifier received from the server. For example: /films/123. 64 | 65 | A page with a detailed description of the film is available to all users. 66 | 67 | The page header contains the following set of information: 68 | 69 | * Large poster. 70 | * Film cover. 71 | * Movie title. 72 | * Genre. 73 | * Year of release. 74 | * Button to start viewing. 75 | * Button to add to the “To watch” list. 76 | * Button to go to the page for adding a review. 77 | 78 | More detailed information about the film is presented on three tabs: 79 | 80 | * Overview. General information. 81 | * Details. Extended information. 82 | * Reviews. Reviews. 83 | 84 | 85 | #### 1.1.2.1. Tabs on the movie description page 86 | 87 | Review. General information about the film: 88 | 89 | * Film description. 90 | * Grade. For example, 8.9 (always one decimal place). 91 | * Rating description (Bad, Normal, Good, Very Good, Excellent). 92 | * Number of votes. 93 | * Director. 94 | * List of actors. 95 | 96 | Details. Extended information: 97 | 98 | * Director. 99 | * Cast. 100 | * Duration (hours, minutes). 101 | * Genre. 102 | * Year of release. 103 | * Reviews. List of user reviews. 104 | 105 | #### 1.1.2.2. Film rating 106 | 107 | The textual representation of the film rating is formed according to the following rules: 108 | 109 | * from 0 to 3 - Bad. 110 | * from 3 to 5 - Normal. 111 | * from 5 to 8 - Good. 112 | * from 8 to 10 - Very good. 113 | * 10 - Awesome. 114 | 115 | #### 1.1.2.3. Similar films 116 | 117 | The “More like this” block shows similar films. The block displays up to 4 cards of similar films. 118 | 119 | A list of similar films is downloaded from the server (see “Routes”). 120 | 121 | The cards contain the same set of information as the cards on the main page. 122 | 123 | Clicking on a card from the “More like this” block takes you to the “Film” page of the corresponding film. 124 | 125 | #### 1.1.2.4. Reviews 126 | 127 | **Each review contains:** 128 | 129 | * Review text. 130 | * User rating. 131 | * Username. 132 | * Review date in the format: Month (full name), day, year. For example: December 24, 2018. 133 | * Adding a new review is done by clicking the “Add review” button. The button should only be visible to authorized users. 134 | 135 | #### 1.1.3. Feedback form 136 | 137 | When you click on the “Add review” button, you go to the Add review page (/films/:id/review). 138 | 139 | The page is available only to authorized users. Unauthorized users are redirected to the Sign In page. 140 | 141 | The user rates the film from 1 to 10. The rating is given by highlighting a certain number of stars. If a film does not yet have ratings from users, its rating on the server is 0. 142 | 143 | The review text must be no less than 50 and no more than 400 characters. 144 | 145 | Until the user has given a rating and entered the allowed amount of text, the button to send a review is not active. 146 | 147 | When you click the "Post" button and submit the data, the "Submit" button and the entire form should be blocked. The form and button are unlocked if the submission is successful or if an error occurs. 148 | 149 | If the form is submitted successfully, the user is redirected to the current movie card. 150 | 151 | If an error occurs, the user should be notified. The way the error is displayed is at the discretion of the developer. 152 | 153 | #### 1.1.4. MyList page 154 | 155 | The page contains information about films added to the “To Watch” list. 156 | 157 | The data for the MyList page is always loaded from the server. A separate route is provided for this (see section “Interaction with the server”). 158 | 159 | Adding to the “To Watch” list is done by clicking on the “+ MyList” button on the “Film” page and on the main page for a promotional film. The “+ MyList” button is replaced with the “✓ MyList” button. 160 | 161 | If a movie has already been added to the “To Watch” list, clicking on the “✓ My List” button removes the movie from the list. The “✓ MyList” button is replaced with the “+ MyList” button. 162 | 163 | The MyList page is available only to authorized users. Unauthorized users are redirected to the "Sign In" page. 164 | 165 | Clicking on a film card (image, title) takes you to the “Film” page with a detailed description of the film. 166 | 167 | #### 1.1.5. Sign In page 168 | 169 | The “Sign in” page is available at /login. 170 | 171 | To enter the service, the user enters a login (email) and password. 172 | 173 | Since the service does not have the ability to register, the login and password can be anything, but not empty. 174 | 175 | The correct email must be entered in the “login” field. 176 | 177 | A valid password must be entered in the “password” field. A valid password is a password that consists of at least one letter and number. 178 | 179 | The page is available only to unauthorized users. Authorized users are redirected to the main page. 180 | 181 | Error information is displayed in the error block. 182 | 183 | #### 1.1.6. Watching films 184 | 185 | When you click on the “Play” button, the player is drawn and the selected movie begins to be shown. An animated spinner is displayed as the movie loads. The implementation of the spinner is left to the discretion of the developer. 186 | 187 | **Player functionality:** 188 | 189 | * "Play/Pause". Start/stop video. 190 | * "Fullscreen". Switch to full screen mode. 191 | * "Time Left". Remaining video playback time. The time is displayed in the format -MM:SS - minutes, seconds or -HH:MM:SS - hours, minutes, seconds, if the video duration is more than one hour, for example: 192 | * Less than an hour: -53:12; 193 | * More than an hour: -01:45:35. 194 | * "Exit". Stop viewing. The player is hiding. 195 | * The player is implemented using