Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull request to make a code review #1

Open
wants to merge 63 commits into
base: release_1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
56dfa24
create md file with desciption of my workflow
KhristenkoE Aug 1, 2022
72f4eb4
add images for the 1 step of my workflow
KhristenkoE Aug 1, 2022
493b6fd
update and add more tasks to tasks.md
KhristenkoE Aug 1, 2022
0377ce8
edit text in tasks/1 README.md
KhristenkoE Aug 1, 2022
96c7090
add tasks/2
KhristenkoE Aug 1, 2022
5dc6739
add tasks/3
KhristenkoE Aug 1, 2022
013a2ca
remove wrong bracket in tasks.md
KhristenkoE Aug 1, 2022
fca218e
update tasks in tasks.md
KhristenkoE Aug 1, 2022
3a6ba10
initialize react+typescript+webpack configs
KhristenkoE Aug 2, 2022
ff2ed21
add rules to .gitignore
KhristenkoE Aug 2, 2022
38fd092
add uuid package
KhristenkoE Aug 2, 2022
f687773
Add context with mock data
KhristenkoE Aug 2, 2022
d447c11
add basic components layout
KhristenkoE Aug 2, 2022
c5cad12
add css loaders
KhristenkoE Aug 2, 2022
bf59be7
add config for css parsing
KhristenkoE Aug 2, 2022
e2e947c
update yarn.lock
KhristenkoE Aug 2, 2022
b59e49a
add markup for transactions list
KhristenkoE Aug 2, 2022
ad62c6d
update to-dos
KhristenkoE Aug 2, 2022
0cbe43e
add react-router-dom
KhristenkoE Aug 3, 2022
733ab38
update webpack for proper routing handling
KhristenkoE Aug 3, 2022
0ea9771
add TransactionDetails and connect transactions with data
KhristenkoE Aug 3, 2022
e00444e
add Home page
KhristenkoE Aug 3, 2022
63543f3
add pages for Card data
KhristenkoE Aug 3, 2022
25e2d33
add 404 page
KhristenkoE Aug 3, 2022
b13c50f
add global styles
KhristenkoE Aug 3, 2022
7cf3588
add Filters
KhristenkoE Aug 3, 2022
9159357
add routing to index file
KhristenkoE Aug 3, 2022
a97c136
add routing to App
KhristenkoE Aug 3, 2022
947cb13
update tasks in tasks.md
KhristenkoE Aug 3, 2022
9ae2a41
remove basename from BrowserRouter
KhristenkoE Aug 4, 2022
2edd12c
add breadcrumbs to App
KhristenkoE Aug 4, 2022
8920f95
add breadcrumbs
KhristenkoE Aug 4, 2022
cc634de
fix Filter
KhristenkoE Aug 4, 2022
51e83f2
make FilterDate controllable
KhristenkoE Aug 4, 2022
3352b8a
fix logic and styles of FilterRange
KhristenkoE Aug 4, 2022
8169104
fix logic and styles of FilterSelect
KhristenkoE Aug 4, 2022
52642d4
add BreadcrumbsContext
KhristenkoE Aug 4, 2022
e9bbd79
add filters for Cards to DataContext
KhristenkoE Aug 4, 2022
f79ba71
add margin to body
KhristenkoE Aug 4, 2022
de5ec20
add normalize.css
KhristenkoE Aug 4, 2022
3c6f8b1
fix Filter typings
KhristenkoE Aug 4, 2022
0dcbada
fix 404 page
KhristenkoE Aug 4, 2022
58b9453
add filtration and detalize Card
KhristenkoE Aug 4, 2022
e7bfcf4
add styles fro Transactions
KhristenkoE Aug 4, 2022
fad621b
add title style to Transaction
KhristenkoE Aug 4, 2022
c124506
add filter logic to TransactionsList
KhristenkoE Aug 4, 2022
ddc4058
fix info in TransactionDetails
KhristenkoE Aug 4, 2022
f23297b
edit home styles
KhristenkoE Aug 4, 2022
3563cf1
finish tasks
KhristenkoE Aug 4, 2022
5500ffd
Update README.md
KhristenkoE Aug 4, 2022
16d59de
Update README.md
KhristenkoE Aug 4, 2022
1979606
fix breadcrumbs
KhristenkoE Aug 4, 2022
dfe55a7
Merge branch 'main' of github.com:KhristenkoE/bank-account
KhristenkoE Aug 4, 2022
445c906
remove unused dependency
KhristenkoE Aug 5, 2022
1280f5f
Describe task 2 better
KhristenkoE Aug 10, 2022
e1b9009
add more info to task 2
KhristenkoE Aug 10, 2022
97678e3
Update task 3
KhristenkoE Aug 10, 2022
80d13b4
Update README.md
KhristenkoE Aug 10, 2022
4c1274b
add fixes
KhristenkoE Aug 10, 2022
287c4cc
Merge branch 'main' of github.com:KhristenkoE/bank-account
KhristenkoE Aug 10, 2022
a5a27c9
remove comments
KhristenkoE Aug 10, 2022
722fbb9
Update README.md
KhristenkoE Aug 10, 2022
b0bb14b
Update README.md
KhristenkoE May 7, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
]
}
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_size = 2
indent_style = tab
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
.vscode
yarn-error.log
.DS_Store
.env
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
# bank-account

A showcase project of how Eugene Khristenko does his job.

### Stages
1. Look at tasks
2. Look at commits
3. See how the flow went
3. See how I implemented the project
4. Look at the pull request and see code review that I did for my self, as I would for someone else

### Getting started
To start the project localy you need to:

- `git clone git@github.com:KhristenkoE/bank-account.git`
- `cd bank-account`
- `yarn install` or `npm install`
- `yarn start` or `npm run start`
- open `http://localhost:8080`
5 changes: 5 additions & 0 deletions declaration.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// declaration.d.ts
declare module '*.css' {
const content: Record<string, string>;
export default content;
}
33 changes: 33 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "bank-account",
"version": "1.0.0",
"main": "index.js",
"repository": "git@github.com:KhristenkoE/bank-account.git",
"author": "Eugene Khristenko <ekhristenko0@gmail.com>",
"license": "MIT",
"scripts": {
"start": "webpack serve --config webpack.config.js --mode development --hot",
"build": "webpack --mode production"
},
"devDependencies": {
"@babel/core": "^7.17.2",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.18.6",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@types/uuid": "^8.3.4",
"babel-loader": "^8.2.3",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"style-loader": "^3.3.1",
"typescript": "^4.7.4",
"uuid": "^8.3.2",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.9.3",
"react-router-dom": "6"
}
}
37 changes: 37 additions & 0 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import BreadcrumbsContextProvider from '../../contexts/BreadcrumbsContext';
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get rid of these hard-to-read and write paths ( ../../someComponent ) you can use aliases (@someComponent). They can be configured in the webpack.config and tsconfig.json for typing to work correctly

import DataContext, { initialContext as initialDataContext } from '../../contexts/DataContext';
import FiltersContextProvider from '../../contexts/FiltersContext';
import CardDetails from '../../pages/CardDetails/CardDetails';
import CardsList from '../../pages/CardsList/CardsList';
import Home from '../../pages/Home/Home';
import TransactionDetails from '../../pages/TransactionDetails/TransactionDetails';
import TransactionsList from '../../pages/TransactionsList/TransactionsList';
import _404 from '../../pages/_404/_404';
import Breadcrumbs from '../Breadcrumbs/Breadcrumbs';

const App = () => {
return (
<DataContext.Provider value={initialDataContext}>
<FiltersContextProvider>
<BreadcrumbsContextProvider>
<Breadcrumbs />
<Routes>
<Route path="transactions" element={<TransactionsList />} />
<Route path="transactions/:transactionID" element={<TransactionDetails />} />
<Route path="transactions/:transactionID/:cardID" element={<CardDetails />} />
<Route path="cards" element={<CardsList />} />
<Route path="cards/:cardID" element={<CardDetails />} />
<Route path="cards/:cardID/transactions" element={<TransactionsList />} />
<Route path="cards/:cardID/transactions/:transactionID" element={<TransactionDetails />} />
<Route path="/" element={<Home />} />
<Route path="*" element={<_404 />} />
</Routes>
</BreadcrumbsContextProvider>
</FiltersContextProvider>
</DataContext.Provider>
)
};

export default App;
35 changes: 35 additions & 0 deletions src/components/Breadcrumbs/Breadcrumbs.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.list {
padding: 20px 20px;
margin: 0;
display: flex;
list-style: none;
}

.list li {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not too good to use specific selectors (like li or li button) because in your jsx you can change the element to div for example, but will forget to change it here.

margin-right: 10px;
position: relative;
}

.list li button {
border: none;
background-color: transparent;
color: #959595;
cursor: pointer;
}

.list li button.breadcrumbActive {
color: white;
cursor: default;
}

.list li:not(:last-child):before {
content: '';
position: absolute;
height: 5px;
width: 5px;
background: #27303c;
border-radius: 100%;
top: 50%;
transform: translateY(-1px);
right: -7px;
}
27 changes: 27 additions & 0 deletions src/components/Breadcrumbs/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { BreadcrumbsContext } from '../../contexts/BreadcrumbsContext';
import styles from './Breadcrumbs.module.css';

const Breadcrumbs = () => {
const { breadcrumbs } = useContext(BreadcrumbsContext);
const navigate = useNavigate();

const onBreadcrumbClick = (url: string, index: number) => {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

index is not used

navigate(url);
}

return (
<nav>
<ul className={styles.list}>
{breadcrumbs.map(({ url, name }, index) => (
<li key={index}>
<button className={index === breadcrumbs.length - 1 ? styles.breadcrumbActive : ''} onClick={() => onBreadcrumbClick(url, index)}>{name}</button>
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this libraries like "class names" can be used https://www.npmjs.com/package/classnames

</li>
))}
</ul>
</nav>
);
};

export default Breadcrumbs;
72 changes: 72 additions & 0 deletions src/components/Filter/Filter.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.filterButton {
padding: 10px 20px;
background-color: #141921;
border-radius: 5px;
text-decoration: none;
color: inherit;
border: none;
position: relative;
}

.filterButton:hover {
cursor: pointer;
transform: scale(1.01);
background-color: #1d232e;
}

.filterButtonIndicate::before {
content: '';
position: absolute;
top: 5px;
right: 7px;
width: 5px;
height: 5px;
background-color: #b0104b;
border-radius: 100%;
}

.filtersBlock {
background-color: #202630;
display: block;
border-radius: 5px;
}

.filtersBlockContent {
padding: 20px 20px;
}

.filterBlockClosed {
display: none;
}

.title {
margin: 0 0 20px 0;
}

.list {
margin: 0 0 20px 0;
padding: 0;
list-style: none;
display: grid;
column-gap: 40px;
row-gap: 10px;
}

.filter {
display: grid;
grid-auto-flow: column;
column-gap: 10px;
justify-content: flex-start;
}

.clearFilters {
border: none;
border-radius: 5px;
padding: 5px 12px;
background-color: #c6cfde;
cursor: pointer;
}

.clearFilters:hover {
background-color: #e6eaf1;
}
75 changes: 75 additions & 0 deletions src/components/Filter/Filter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { AppliedFilter, Filter as FilterInterface, FilterName, FilterType } from '../../interfaces/Filter';
import styles from './Filter.module.css';
import FilterDate from './FilterDate/FilterDate';
import FilterRange from './FilterRange/FilterRange';
import FilterSelect from './FilterSelect/FilterSelect';

interface Props {
filters: FilterInterface[];
intialAppliedFilters: AppliedFilter;
onChange(value: string | { min: number, max: number }, name: string, type: FilterType): void;
onClear(): void;
}

const Filter = ({
filters,
intialAppliedFilters,
onChange,
onClear,
}: Props) => {
const [isOpen, setIsOpen] = useState(false);
const filterContainerRef = useRef<HTMLElement>(null);

useEffect(() => {
filterContainerRef.current = document.getElementById('filters-block');
}, []);

const onChangeSelect = (value: string, name: string, type: FilterType) => {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line: 29, 33, 37 - not required function mapping.

onChange(value, name, type);
};

const onRangeChange = (value: { min: number, max: number }, name: string, type: FilterType) => {
onChange(value, name, type);
};

const onDateChange = (value: string, name: string, type: FilterType) => {
onChange(value, name, type);
};

return (
<article>
<button onClick={() => setIsOpen((isOpenPrev) => !isOpenPrev)} className={`${styles.filterButton} ${Object.keys(intialAppliedFilters).length ? styles.filterButtonIndicate : ''}`}>Filters</button>
{filterContainerRef.current && ReactDOM.createPortal(
<article className={`${styles.filtersBlock} ${!isOpen ? styles.filterBlockClosed : ''}`}>
<div className={styles.filtersBlockContent}>
<h4 className={styles.title}>Filters</h4>
<ul className={styles.list}>
{filters.map(({ label, name, options, from, to, type }) => {
return (
<li className={styles.filter} key={label}>
<label htmlFor={label}>{name}</label>
{type === FilterType.SELECT_ONE && (
<FilterSelect initialValue={(intialAppliedFilters[label] || 'All') as string} onChange={(value) => onChangeSelect(value, label, FilterType.SELECT_ONE)} name={label} options={options} />
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line: 54, 57 "magic numbers", What are 'All' and '' and why are they the initial values? - these things need to be in constants

)}
{type === FilterType.DATE && (
<FilterDate initialValue={(intialAppliedFilters[label] || '') as string} onChange={(value) => onDateChange(value, label, FilterType.DATE)}/>
)}
{type === FilterType.RANGE && (
<FilterRange initialValue={intialAppliedFilters[label] as { min: number; max: number }} min={from} max={to} onChange={(value) => onRangeChange(value, label, FilterType.RANGE)}/>
)}
</li>
)
})}
</ul>
<button className={styles.clearFilters} onClick={onClear}>Clear filters</button>
</div>
</article>,
filterContainerRef.current
)}
</article>
);
};

export default Filter;
7 changes: 7 additions & 0 deletions src/components/Filter/FilterDate/FilterDate.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.datePicker {
background-color: #29303d;
color: white;
border-radius: 5px;
padding: 3px 10px;
border: none;
}
29 changes: 29 additions & 0 deletions src/components/Filter/FilterDate/FilterDate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React, { useEffect } from 'react';
import styles from './FilterDate.module.css';

interface Props {
onChange(value: string): void;
initialValue?: string;
}

const FilterDate = ({
onChange,
initialValue,
}: Props) => {
const [value, setValue] = React.useState(initialValue);

useEffect(() => {
setValue(initialValue);
}, [initialValue]);

const changeValue = (value: string) => {
onChange(value);
setValue(value);
};

return (
<input className={styles.datePicker} value={value} onChange={(e) => changeValue(e.target.value)} type="date" />
)
}

export default FilterDate;
5 changes: 5 additions & 0 deletions src/components/Filter/FilterRange/FilterRange.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.wrapper {
display: grid;
grid-auto-flow: column;
column-gap: 10px;
}
Loading