Git Product home page Git Product logo

vhs-frontend-lab's Issues

Migrate from CRA to Vite

This app uses create-react-app as dev tooling. Let's migrate that to Vite to get all the benefits of faster performance when hot reloading, bundling and cold starting the app.

Use finally in try/catch if running identical logic

const deleteEntry = async () => {
try {
const response = await axios.delete(`/api/vhs/${VHS.id}`);
console.log(response);
navigate('/explore');
} catch (error) {
console.error(error);
navigate('/explore');
}
};

You have the same navigate statement called both in try and catch. Use the finally clause to run the shared statement.

https://www.w3schools.com/jsref/jsref_try_catch.asp

Error when deleting VHS entry

When using a DELETE request to delete a VHS that doesn't have a thumbnail, server responds with 500 - works fine when deleting a VHS that has a thumbnail.

WTR:
Make a DELETE request for a VHS that doesn't have a thumbnail. Observe server response.

Expected result:
Server responds with 204, as it does when deleting a VHS with a thumbnail, deletes VHS.

Actual result:
Server responds with 500, "Internal server error", deletes VHS.

Additional info:

[Nest] 5084  - 11/22/2022, 11:58:24 AM   ERROR [ExceptionsHandler] The "path" argument must be of type string or an instance of Buffer or URL. Received null
TypeError: The "path" argument must be of type string or an instance of Buffer or URL. Received null
    at Object.unlink (node:fs:1752:10)
    at VhsService.deleteVhs (F:\Frontend\Projects\vhs-frontend-lab\vhs-backend\src\vhs\vhs.service.ts:62:8)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at F:\Frontend\Projects\vhs-frontend-lab\vhs-backend\node_modules\@nestjs\core\router\router-execution-context.js:46:28
    at F:\Frontend\Projects\vhs-frontend-lab\vhs-backend\node_modules\@nestjs\core\router\router-proxy.js:9:17

fs.unlink(vhs.thumbnail, (error) => {

Add husky

In order to make sure that our whole project is properly linted and formatted, especially when working in a team, we sometimes need to run some actions on our codebase while performing a git commit or git push.

There is a tool that enables us to do this in Node based projects and it's called Husky: https://typicode.github.io/husky/#/

Read about how it works and set it up in your project. On all commits, run eslint and prettier to lint and format the whole project.

Handle non existing routes with the NotFound component

Currently you have a dedicated route for /not-found. What happens if the user enters your domain and inputs a path that your router doesn't handle, like /denfiuaebrfur? React-router enables us to handle such a case as well. Make it so that non existing routes all navigate to the NotFound component.

Filter VHS using backend query params

{searching
? filteredList.map(
(item) =>
item.id && (
<VhsThumbnail
key={item.id}
image={
item.thumbnail
? item.thumbnail.replace(/\\/g, "/")
: placeholder
}
vhsId={item.id}
vhsTitle={item.title}
/>
)
)
: vhsList.map(
(item) =>
item.id && (
<VhsThumbnail
key={item.id}
image={
item.thumbnail
? item.thumbnail.replace(/\\/g, "/")
: placeholder
}
vhsId={item.id}
vhsTitle={item.title}
/>
)
)}

  • backend GET route for all VHS takes query params with which you can filter VHS tapes by name, description, genre and such, look it up and use it so that you can get rid of filteredVHS

Improve VHS Details component

import React, { useEffect, useState } from "react";
import { Link, useParams, useNavigate } from "react-router-dom";
import { VHS } from "../types";
import axios from "axios";
import Edit from "./Edit";
// @ts-ignore
import placeholder from "../assets/placeholder.jpg";
type Props = {};
export default function VHSDetails({}) {
function convertDuration(duration: number) {
const hours = Math.floor(duration / 60);
const minutes = duration % 60;
return `${hours}:${minutes}`;
}
const { vhsId } = useParams();
const notFoundLink = useNavigate();
const [vhsInfo, setVhsInfo] = useState<VHS>();
const fetchSingleVHS = async () => {
try {
const response = await axios.get(`/api/vhs/${vhsId}`);
setVhsInfo(response.data);
} catch (err) {
console.log(err);
notFoundLink("/notfound");
}
};
useEffect(() => {
fetchSingleVHS();
}, []);
return (
<div>
{vhsInfo && (
<div>
<h1>{vhsInfo.title}</h1>
<div>Description: {vhsInfo.description}</div>
<div>Duration: {convertDuration(vhsInfo.duration)}</div>
<div>Genre: {vhsInfo.genre}</div>
<div>Release year: {vhsInfo.releasedAt}</div>
<div>Rental price: {vhsInfo.rentalPrice} coins</div>
<img
src={
vhsInfo.thumbnail
? vhsInfo.thumbnail.replace(/\\/g, "/")
: placeholder
}
alt=""
/>
<Link to="/edit" state={vhsInfo}>
<button>EDIT</button>
</Link>
</div>
)}
</div>
);
}

  • find another image that is either SVG or PNG and get rid of that ts-ignore
  • move convertDuration function outside of component somewhere to utils

Set up and fully implement i18n

I18n or internationalization is a technique we use in coding projects that solves the issue of "content shouldn't live in code".

When we have components that show some textual content we never want to hardcode strings into the code, but rather extract them into structured JSON files where we can put them under certain keys and then we use the keys in the code.

This way it's possible to make several JSON objects with the same keys but different values depending on the active language on user's system for example, and that's localization.

Set up i18n in your project and implement it (extract all strings you have hardcoded). Use https://react.i18next.com/getting-started

Improve Header component

import React from "react";
import { Link } from "react-router-dom";
type Props = {};
export default function Header({}: Props) {
return (
<div>
<Link to="/">Home</Link> <br />
<Link to="/explore">Discovery</Link> <br />
<Link to="/create">Create new VHS</Link> <br />
</div>
);
}

Remove Props if not used. If used, make it an interface instead of type.
Additionally, links are separated with a <br> tag, let's change that and make a flex container with horizontal direction and beautify the navbar with CSS. :)

Clean up package.json

{
"name": "vhs-frontend",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:3000",
"dependencies": {
"@hookform/resolvers": "^2.9.10",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.3",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
"axios": "^1.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.40.0",
"react-router-dom": "^6.4.3",
"react-scripts": "5.0.1",
"typescript": "^4.9.3",
"web-vitals": "^2.1.4",
"zod": "^3.20.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

  • install prettier to dev dependencies and set up .prettierrc.json file and .prettierignore file in project root
  • move all @types/* packages to dev dependencies

Add Dockerfile to frontend project

It's common practice nowadays to use containerization for all services we deploy to the web. Since this is a new topic for you, I will route you to Docker's getting started documentation: https://docs.docker.com/get-started/

This section has 10 parts in the sidebar which you should read to start understanding the basics of containerizing an application. Also, this video is a gem: https://www.youtube.com/watch?v=d-PPOS-VsC8&list=PLvjWHH6VW-WJJHRLp9kdpupCi6O9QXn2I&index=31

When you get to know Docker a bit, try to construct a Dockerfile for your frontend application. Also, include a .dockerignore file.

Add eslint configuration to the project

It's important to use linters in coding projects because they make sure your codebase follows a set of rules that will make it consistent, more readable and follow some best practice guidelines.

For frontend projects, we use a tool called ESLint: https://eslint.org/

Do some research on how this works and how it is configured and then configure some eslint rules on the project. Feel free to use any guides online and extend existing plugins for eslint rules.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.