Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ciehgiordani committed Mar 10, 2024
1 parent b86a571 commit e3c53e1
Show file tree
Hide file tree
Showing 20 changed files with 659 additions and 130 deletions.
113 changes: 1 addition & 112 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,112 +1 @@
# React homework template

Цей проект був створений за допомогою
[Create React App](https://github.com/facebook/create-react-app). Для знайомства
і налаштування додаткових можливостей
[звернися до документації](https://facebook.github.io/create-react-app/docs/getting-started).

## Створення репозиторію за шаблоном

Використовуй цей репозиторій організації GoIT як шаблон для створення репозиторію
свого проєкта. Для цього натисни на кнопку `«Use this template»` і вибери опцію
`«Create a new repository»`, як показано на зображенні.

![Creating repo from a template step 1](./assets/template-step-1.png)

На наступному кроці відкриється сторінка створення нового репозиторію. Заповни поле
його імені, переконайся що репозиторій публічний, після чого натисни кнопку
`«Create repository from template»`.

![Creating repo from a template step 2](./assets/template-step-2.png)

Після того як репозиторій буде створено, необхідно перейти в налаштування
створеного репозиторію на вкладку `Settings` > `Actions` > `General` як
показано на зображенні.

![Settings GitHub Actions permissions step 1](./assets/gh-actions-perm-1.png)

Проскроливши сторінку до самого кінця, у секції `«Workflow permissions»` вибери
опцію `«Read and write permissions»` і постав галочку в чекбоксі. Це
необхідно для автоматизації процесу деплою проєкту.

![Settings GitHub Actions permissions step 2](./assets/gh-actions-perm-2.png)

Тепер у тебе є особистий репозиторій проекту, зі структурою файлів і папок
репозиторію-шаблону. Далі працюй із ним як із будь-яким іншим особистим репозиторієм,
клонуй його собі на комп'ютер, пиши код, роби комміти і відправляй їх на
GitHub.

## Підготовка до роботи

1. Переконайся що на комп'ютері встановлено LTS-версія Node.js.
[Завантаж і встанови](https://nodejs.org/en/) її якщо необхідно.
2. Встанови базові залежності проєкту командою `npm install`.
3. Запусти режим розробки, виконавши команду `npm start`.
4. Перейди в браузері за адресою [http://localhost:3000](http://localhost:3000).
Ця сторінка буде автоматично перезавантажуватися після збереження змін у файлах проєкту.

## Деплой

Продакшн версія проєкту буде автоматично проходити лінтинг, збиратися і
деплоїтися на GitHub Pages, у гілку `gh-pages`, щоразу, коли оновлюється
гілка `main`. Наприклад, після прямого пушу або прийнятого пул-реквесту. Для цього
необхідно у файлі `package.json` відредагувати поле `homepage`, замінивши
`your_username` і `your_repo_name` на свої, і відправити зміни на GitHub.

```json
"homepage": "https://your_username.github.io/your_repo_name/"
```

Далі необхідно зайти в налаштування GitHub-репозиторію (`Settings` > `Pages`) і
виставити роздачу продакшн-версії файлів із папки `/root` гілки `gh-pages`, якщо
це не було зроблено автоматично.

![GitHub Pages settings](./assets/repo-settings.png)

### Статус деплоя

Статус деплою крайнього коміту відображається іконкою біля його ідентифікатора.

- **Жовтий колір** - виконується збірка і деплой проєкту.
- **Зелений колір** - деплой завершився успішно.
- **Червоний колір** - під час лінтингу, сборки або деплою сталася помилка.

Детальнішу інформацію про статус можна подивитися, клікнувши на іконку, і
у вікні, що випадає, перейти за посиланням `Details`.

![Deployment status](./assets/deploy-status.png)

### Жива сторінка

Через якийсь час, зазвичай кілька хвилин, живу сторінку можна буде подивитися
за адресою, вказаною у відредагованій властивості `homepage`. Наприклад, ось
посилання на живу версію для цього репозиторію
[https://goitacademy.github.io/react-homework-template](https://goitacademy.github.io/react-homework-template).

Якщо відкривається порожня сторінка, переконайся, що у вкладці `Console` немає помилок
пов'язаних із неправильними шляхами до CSS і JS файлів проєкту (**404**). Швидше
за все у тебе неправильне значення властивості `homepage` у файлі `package.json`.

### Маршрутизація

Якщо додаток використовує бібліотеку `react-router-dom` для маршрутизації,
необхідно додатково налаштувати компонент `<BrowserRouter>`, передавши у пропе
`basename` точну назву твого репозиторію. Слеш на початку рядка обов'язковий.

```jsx
<BrowserRouter basename="/your_repo_name">
<App />
</BrowserRouter>
```

## Як це працює

![How it works](./assets/how-it-works.png)

1. Після кожного пушу в гілку `main` GitHub-репозиторія, запускається спеціальний
скрипт (GitHub Action) з файла `.github/workflows/deploy.yml`.
2. Усі файли репозиторію копіюються на сервер, де проект ініціалізується і
проходить лінтинг і збірку перед деплоєм.
3. Якщо всі кроки пройшли успішно, зібрана продакшн-версія файлів проєкту
відправляється в гілку `gh-pages`. В іншому випадку, в лозі виконання
скрипта буде вказано в чому проблема.
# goit-react-hw-01
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "react-homework-template",
"name": "goit-react-hw-1",
"version": "0.1.0",
"private": true,
"homepage": "https://goitacademy.github.io/react-homework-template/",
"homepage": "https://ciehgiordani.github.io/goit-react-hw-1/",
"dependencies": {
"@testing-library/jest-dom": "^5.16.3",
"@testing-library/react": "^12.1.4",
Expand Down
43 changes: 29 additions & 14 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
// FIRST NEED TO IMPORT THE CREATED COMPONENTS
import { Profile } from './Profile/Profile';
import user from '../data/user.json'; //IT IS THE DOWNLOADED JSON FORM THE TASK

import { Statistics } from './Statistics/Statistics';
import data from '../data/data.json'; //IT IS THE DOWNLOADED JSON FORM THE TASK

import { FriendList } from './FriendList/FriendList';
import friends from '../data/friends.json'; //IT IS THE DOWNLOADED JSON FORM THE TASK

import { TransactionHistory } from './TransactionHistory/TransactionHistory';
import transactions from '../data/transactions.json'; //IT IS THE DOWNLOADED JSON FORM THE TASK

export const App = () => {
return (
<div
style={{
height: '100vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
fontSize: 40,
color: '#010101'
}}
>
React homework template
</div>
return (
//<> </> is Short Syntax for React Fragment instead of using parent element like div
<>
<Profile
username={user.username}
tag={user.tag}
location={user.location}
avatar={user.avatar}
stats={user.stats}
/>

<Statistics title="Upload Stats" stats={data} />
<FriendList friends={friends} />
<TransactionHistory items={transactions} />
</>
);
};
};
26 changes: 26 additions & 0 deletions src/components/FriendList/FriendList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import PropTypes from 'prop-types';
import { FriendListItem } from 'components/FriendListItem/FriendListItem';
import css from './FriendList.module.css';

export const FriendList = ({ friends }) => {
return (
<ul className={css.friendList}>
{friends.map(({ avatar, name, isOnline, id }) => (
<FriendListItem
key={id}
avatar={avatar}
name={name}
isOnline={isOnline}
/>
))}
</ul>
);
};

FriendList.propTypes = {
friends: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
})
).isRequired,
};
6 changes: 6 additions & 0 deletions src/components/FriendList/FriendList.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.friendList {
margin: 50px auto;
width: 300px;
list-style-type: none;
border-radius: 5px;
}
26 changes: 26 additions & 0 deletions src/components/FriendListItem/FriendListItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import css from './FriendListItem.module.css';
import PropTypes from 'prop-types';

export const FriendListItem = ({ avatar, name, isOnline }) => {

// Generate Random Color
const generateRandomColor = () => {
return `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(
Math.random() * 256
)}, ${Math.floor(Math.random() * 256)})`;
};

return (
<li className={css.friendListItem}>
<span className={isOnline ? css.online : css.offline}></span>
<img className={css.avatar} style={{ backgroundColor: generateRandomColor() }} src={avatar} alt="User avatar" width="70" />
<p className={css.name}>{name}</p>
</li>
);
};

FriendListItem.propTypes = {
avatar: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
isOnline: PropTypes.bool.isRequired,
};
40 changes: 40 additions & 0 deletions src/components/FriendListItem/FriendListItem.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.friendListItem {
padding: 10px 15px;
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 15px;
/* height: 60px; */
border-radius: 5px;
background: white;
box-shadow: 0px 2px 1px 0px rgba(46, 47, 66, 0.08),
0px 1px 1px 0px rgba(46, 47, 66, 0.16),
0px 1px 6px 0px rgba(46, 47, 66, 0.08);
}

.avatar{
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.2);
}
.name {
font-size: 22px;
line-height: 1.62;
font-weight: 500;
color: black;
}
.status {
width: 20px;
height: 20px;
border-radius: 50%;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}

.online {
composes: status;
background-color: green;
}

.offline {
composes: status;
background-color: red;
}
42 changes: 42 additions & 0 deletions src/components/Profile/Profile.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import PropTypes from 'prop-types';
import css from './Profile.module.css';

export const Profile = ({ username, tag, location, avatar, stats }) => {
return (
<div className={css.profile}>
<div className={css.description}>
<img src={avatar} alt="User avatar" className={css.avatar} />
<p className={css.name}>{username}</p>
<p className={css.userInfo}>@{tag}</p>
<p className={css.userInfo}>{location}</p>
</div>

<ul className={css.stats}>
<li className={css.item}>
<span className={css.label}>Followers</span>
<span className={css.quantity}>{stats.followers}</span>
</li>
<li className={css.item}>
<span className={css.label}>Views</span>
<span className={css.quantity}>{stats.views}</span>
</li>
<li className={css.item}>
<span className={css.label}>Likes</span>
<span className={css.quantity}>{stats.likes}</span>
</li>
</ul>
</div>
);
};

Profile.propTypes = {
username: PropTypes.string.isRequired,
tag: PropTypes.string.isRequired,
location: PropTypes.string.isRequired,
avatar: PropTypes.string.isRequired,
stats: PropTypes.shape({
followers: PropTypes.number.isRequired,
views: PropTypes.number.isRequired,
likes: PropTypes.number.isRequired,
}).isRequired,
};
Loading

0 comments on commit e3c53e1

Please sign in to comment.