PR-610983: Creating the example project of a List Task App.
This commit is contained in:
parent
f76a89eacb
commit
dd3e108bca
44
.github/workflows/npm-test.yml
vendored
Normal file
44
.github/workflows/npm-test.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
name: Testing package
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ['*']
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
cypress-run-component:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v5 # use the explicit version number
|
||||
with:
|
||||
component: true
|
||||
test-build-package:
|
||||
needs: [ test, cypress-run-component ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
- run: npm run build:frontend
|
21
README.md
21
README.md
@ -1,26 +1,15 @@
|
||||
# Create React SSR
|
||||
# Test List App
|
||||
|
||||
This project aims to have a starter kit for creating a new React app with Server Side Rendering with a backend in go and tools that generally go along with it.
|
||||
|
||||
It is not a project like create-react-app, create-react-app is used as a starter kit that handles all your scripts underneath, this is a project for developers who want more control over their application.
|
||||
|
||||
Tech(Library or Framework) | Version |
|
||||
--- | --- |
|
||||
React (Render Library) | 18.2.0
|
||||
Redux (Global State Management) | 4.2.1
|
||||
React Router DOM (Routing) | 6.16.0
|
||||
Jest (Testing) | 29.7.0
|
||||
Cypress (E2E Testing) | 13.3.0
|
||||
Typescript | 5.2.2
|
||||
This project is an Example of a List of Tasks App.
|
||||
|
||||
## Setup
|
||||
To create a new project run in the terminal:
|
||||
To start the project you need to clone the repo:
|
||||
```
|
||||
npx @aleleba/create-react-go-ssr app-name
|
||||
git clone git@github.com:aleleba/test-list-app.git
|
||||
```
|
||||
Then run:
|
||||
```
|
||||
cd app-name
|
||||
cd test-list-app
|
||||
```
|
||||
You will need to create a new .env file at the root of the project for global config.
|
||||
This is an exaple of config.
|
||||
|
95
package-lock.json
generated
95
package-lock.json
generated
@ -1,15 +1,20 @@
|
||||
{
|
||||
"name": "@aleleba/create-react-go-ssr",
|
||||
"version": "1.0.3",
|
||||
"name": "test-list-app",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@aleleba/create-react-go-ssr",
|
||||
"version": "1.0.3",
|
||||
"name": "test-list-app",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/register": "^7.22.15",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"helmet": "^7.0.0",
|
||||
@ -17,6 +22,7 @@
|
||||
"ignore-styles": "^5.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-list-ui-library": "^1.0.2",
|
||||
"react-redux": "^8.1.3",
|
||||
"react-router-dom": "^6.16.0",
|
||||
"react-router-hash-link": "^2.4.3",
|
||||
@ -36,9 +42,6 @@
|
||||
"workbox-strategies": "^7.0.0",
|
||||
"workbox-streams": "^7.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"create-react-go-ssr": "bin/cli.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.0",
|
||||
"@babel/preset-env": "^7.22.20",
|
||||
@ -2027,6 +2030,75 @@
|
||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.2.tgz",
|
||||
"integrity": "sha512-1DgP7f+XQIJbLFCTX1V2QnxVmpLdKdzzo2k8EmvDOePfchaIGQ9eCHj2up3/jNEbZuBqel5OxiaOJf37TWauRA==",
|
||||
"hasInstallScript": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-svg-core": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.2.tgz",
|
||||
"integrity": "sha512-gjYDSKv3TrM2sLTOKBc5rH9ckje8Wrwgx1CxAPbN5N3Fm4prfi7NsJVWd1jklp7i5uSCVwhZS5qlhMXqLrpAIg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.2.tgz",
|
||||
"integrity": "sha512-LKOwJX0I7+mR/cvvf6qIiqcERbdnY+24zgpUSouySml+5w8B4BJOx8EhDR/FTKAu06W12fmUIcv6lzPSwYKGGg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.2.tgz",
|
||||
"integrity": "sha512-0+sIUWnkgTVVXVAPQmW4vxb9ZTHv0WstOa3rBx9iPxrrrDH6bNLsDYuwXF9b6fGm+iR7DKQvQshUH/FJm3ed9Q==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/free-solid-svg-icons": {
|
||||
"version": "6.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.2.tgz",
|
||||
"integrity": "sha512-sYwXurXUEQS32fZz9hVCUUv/xu49PEJEyUOsA51l6PU/qVgfbTb2glsTEaJngVVT8VqBATRIdh7XVgV1JF1LkA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-common-types": "6.4.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/react-fontawesome": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz",
|
||||
"integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==",
|
||||
"dependencies": {
|
||||
"prop-types": "^15.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "~1 || ~6",
|
||||
"react": ">=16.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanwhocodes/config-array": {
|
||||
"version": "0.11.11",
|
||||
"dev": true,
|
||||
@ -13818,6 +13890,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-list-ui-library": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-list-ui-library/-/react-list-ui-library-1.0.2.tgz",
|
||||
"integrity": "sha512-5f4ET0toaBPrDKdtuSLCiJ88y7TmWmpgXlvK6BiRAcXwFLOaYL8VJgGIhSL+GBny5HG88Rg/PIYeNS6AJeMmYA==",
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-redux": {
|
||||
"version": "8.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
|
||||
|
10
package.json
10
package.json
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "test-list-app",
|
||||
"version": "0.0.1",
|
||||
"version": "1.0.0",
|
||||
"description": "Starter Kit of server side render of react with backend in go",
|
||||
"scripts": {
|
||||
"scripts": {
|
||||
"start": "cd build/server && ./react-server",
|
||||
"start-frontend:dev": "webpack watch --config webpack.config.ts",
|
||||
"start-server:dev": "cd src/server && go run main.go",
|
||||
@ -38,6 +38,11 @@
|
||||
"homepage": "https://github.com/aleleba/create-react-go-ssr#readme",
|
||||
"dependencies": {
|
||||
"@babel/register": "^7.22.15",
|
||||
"@fortawesome/fontawesome-svg-core": "^6.4.2",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.4.2",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.4.2",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.4.2",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"helmet": "^7.0.0",
|
||||
@ -45,6 +50,7 @@
|
||||
"ignore-styles": "^5.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-list-ui-library": "^1.0.2",
|
||||
"react-redux": "^8.1.3",
|
||||
"react-router-dom": "^6.16.0",
|
||||
"react-router-hash-link": "^2.4.3",
|
||||
|
65
src/frontend/actions/ListAction.ts
Normal file
65
src/frontend/actions/ListAction.ts
Normal file
@ -0,0 +1,65 @@
|
||||
/* List */
|
||||
export type TList = {
|
||||
list: TItem[]
|
||||
}
|
||||
|
||||
export interface IListPayload {
|
||||
index?: number
|
||||
item?: TItem
|
||||
}
|
||||
|
||||
export type TItem = {
|
||||
name: string,
|
||||
status: Status
|
||||
}
|
||||
|
||||
export enum Status {
|
||||
TODO = 'TODO',
|
||||
DONE = 'DONE'
|
||||
}
|
||||
|
||||
export interface IAddItemToList {
|
||||
type: ActionTypesList.AddItem
|
||||
payload: IListPayload
|
||||
}
|
||||
|
||||
export interface IChangeStatus {
|
||||
type: ActionTypesList.ChangeStatus
|
||||
payload: IListPayload
|
||||
}
|
||||
|
||||
export interface IDeleteItemToList {
|
||||
type: ActionTypesList.DeleteItem
|
||||
payload: IListPayload
|
||||
}
|
||||
|
||||
export enum ActionTypesList {
|
||||
AddItem = 'ADD_ITEM',
|
||||
ChangeStatus = 'CHANGE_STATUS',
|
||||
DeleteItem = 'DELETE_ITEM'
|
||||
}
|
||||
|
||||
export type TListAction = {
|
||||
type: ActionTypesList
|
||||
payload: IListPayload
|
||||
}
|
||||
|
||||
const addItem = (payload: IAddItemToList) => ({
|
||||
type: ActionTypesList.AddItem,
|
||||
payload
|
||||
});
|
||||
|
||||
const changeStatus = (payload: IChangeStatus) => ({
|
||||
type: ActionTypesList.ChangeStatus,
|
||||
payload
|
||||
});
|
||||
|
||||
const listActions = {
|
||||
addItem,
|
||||
changeStatus
|
||||
};
|
||||
/* List */
|
||||
|
||||
|
||||
|
||||
export default listActions;
|
@ -1,9 +0,0 @@
|
||||
import test, { TTest } from './testAction';
|
||||
|
||||
export type TAction = TTest
|
||||
|
||||
const actions = {
|
||||
test
|
||||
}
|
||||
|
||||
export default actions
|
@ -1,25 +0,0 @@
|
||||
export enum ActionTypesTest {
|
||||
ChangeHello = 'CHANGE_HELLO'
|
||||
}
|
||||
|
||||
export interface IChangeHello {
|
||||
type: ActionTypesTest.ChangeHello
|
||||
payload: IChangeHelloPayload
|
||||
}
|
||||
|
||||
export interface IChangeHelloPayload {
|
||||
hello: any | undefined
|
||||
}
|
||||
|
||||
export type TTest = IChangeHello
|
||||
|
||||
const changeHello = (payload: string) => ({
|
||||
type: ActionTypesTest.ChangeHello,
|
||||
payload
|
||||
})
|
||||
|
||||
const actions = {
|
||||
changeHello
|
||||
}
|
||||
|
||||
export default actions
|
@ -1,38 +0,0 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
import React from 'react';
|
||||
import './InitialComponent.scss';
|
||||
import { connect } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const InitialComponent = ({ hello }: { hello: string }) => {
|
||||
|
||||
return(
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
||||
<p>This is the text from the store of redux: <strong>{hello}</strong></p>
|
||||
<p>
|
||||
Edit <code>src/frontend/InitialComponent.jsx</code> and save to reload.
|
||||
</p>
|
||||
<a
|
||||
className="App-link"
|
||||
href="https://reactjs.org"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Learn React
|
||||
</a>
|
||||
<Link className="App-link" to="/other-component">Other Component</Link>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
hello: state.testReducer.hello
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(InitialComponent);
|
69
src/frontend/components/List.tsx
Normal file
69
src/frontend/components/List.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import React, { useState } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { TItem, ActionTypesList, Status } from '../actions/ListAction';
|
||||
import 'react-list-ui-library/dist/index.css';
|
||||
import { ContainerList, List } from 'react-list-ui-library';
|
||||
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const ListComponent = ({ list, addItem, changeStatus, deleteItem }: {list: TItem[], addItem: (item: TItem) => any, changeStatus: (index: number) => any, deleteItem: (index: number) => any }) => {
|
||||
|
||||
const [itemName, setItemName] = useState<string>('');
|
||||
|
||||
const onClickAddItem = () => {
|
||||
const item: TItem = {
|
||||
name: itemName,
|
||||
status: Status.TODO
|
||||
};
|
||||
if(itemName !== ''){
|
||||
addItem(item);
|
||||
setItemName('');
|
||||
}else{
|
||||
alert('Please, insert a name');
|
||||
}
|
||||
};
|
||||
|
||||
const onChangeInput = (e) => {
|
||||
setItemName(e.target.value);
|
||||
};
|
||||
|
||||
const handleChangeState = (index) => {
|
||||
changeStatus(index);
|
||||
};
|
||||
|
||||
const onClickRemoveItem = (index) => {
|
||||
deleteItem(index);
|
||||
};
|
||||
|
||||
return(
|
||||
<div className="App">
|
||||
<ContainerList title='List App'>
|
||||
<List
|
||||
list={list}
|
||||
valueInput={itemName}
|
||||
placeholderInput='Insert a name of a new item'
|
||||
onChangeInput={onChangeInput}
|
||||
onClickAddItem={onClickAddItem}
|
||||
onClickRemoveItem={onClickRemoveItem}
|
||||
handleChangeState={handleChangeState}
|
||||
/>
|
||||
</ContainerList>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
list: state.listReducer.list
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = (dispatch) => {
|
||||
return {
|
||||
addItem: (item: TItem) => dispatch({ type: ActionTypesList.AddItem, payload: { item: item } }),
|
||||
changeStatus: (index: number) => dispatch({ type: ActionTypesList.ChangeStatus, payload: { index: index } }),
|
||||
deleteItem: (index: number) => dispatch({ type: ActionTypesList.DeleteItem, payload: { index: index } })
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ListComponent);
|
@ -1,18 +0,0 @@
|
||||
import React from 'react';
|
||||
// import logo from '../logo.svg';
|
||||
import './InitialComponent.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const OtherComponent = () => (
|
||||
<div className="App">
|
||||
<header className="App-header">
|
||||
<img src="assets/img/logo.svg" className="App-logo" alt="logo" />
|
||||
<p>
|
||||
Edit <code>src/frontend/OtherComponent.jsx</code> and save to reload.
|
||||
</p>
|
||||
<Link className="App-link" to="/">Initial Component</Link>
|
||||
</header>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default OtherComponent;
|
@ -4,7 +4,7 @@ import { useRoutes } from 'react-router-dom';
|
||||
import routes from '../../routes';
|
||||
|
||||
const PrincipalRoutes = () => {
|
||||
let element = useRoutes(routes);
|
||||
const element = useRoutes(routes);
|
||||
return element;
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,6 @@ describe('Testing Card Component', () => {
|
||||
);
|
||||
});
|
||||
it('Show Text', () => {
|
||||
cy.get('p').contains('Edit src/frontend/InitialComponent.jsx and save to reload.');
|
||||
cy.get('div').contains('List App');
|
||||
});
|
||||
});
|
||||
|
@ -4,20 +4,20 @@ import { ProviderMock } from '@mocks';
|
||||
import App from '@components/App';
|
||||
|
||||
describe('<App/> Component', () => {
|
||||
beforeEach(() => {
|
||||
fetchMock.resetMocks();
|
||||
});
|
||||
beforeEach(() => {
|
||||
fetchMock.resetMocks();
|
||||
});
|
||||
|
||||
it('Should render root <App /> Component', async () => {
|
||||
fetchMock.mockResponseOnce(JSON.stringify({
|
||||
//First Data Fetch
|
||||
data: 'data'
|
||||
}));
|
||||
it('Should render root <App /> Component', async () => {
|
||||
fetchMock.mockResponseOnce(JSON.stringify({
|
||||
//First Data Fetch
|
||||
data: 'data'
|
||||
}));
|
||||
|
||||
render(
|
||||
<ProviderMock>
|
||||
<App />
|
||||
</ProviderMock>
|
||||
)
|
||||
})
|
||||
})
|
||||
render(
|
||||
<ProviderMock>
|
||||
<App />
|
||||
</ProviderMock>
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import testReducer from './testReducer';
|
||||
import { IChangeHelloPayload } from '../actions/testAction';
|
||||
import listReducer from './listReducer';
|
||||
import { TList } from '../actions/ListAction';
|
||||
|
||||
export interface IInitialState {
|
||||
testReducer?: IChangeHelloPayload | undefined
|
||||
listReducer?: TList | undefined
|
||||
}
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
// Here comes the reducers
|
||||
testReducer
|
||||
listReducer
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
|
48
src/frontend/reducers/listReducer.ts
Normal file
48
src/frontend/reducers/listReducer.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { ActionTypesList, TListAction, TItem, Status } from '../actions/ListAction';
|
||||
|
||||
const initialState = {
|
||||
list: []
|
||||
};
|
||||
|
||||
const listReducer = (state = initialState, action: TListAction) => {
|
||||
switch (action.type){
|
||||
case ActionTypesList.AddItem: {
|
||||
const newList = [
|
||||
...state.list,
|
||||
action.payload.item
|
||||
];
|
||||
return {
|
||||
list: newList
|
||||
};
|
||||
}
|
||||
case ActionTypesList.ChangeStatus: {
|
||||
const itemList = state.list[action.payload.index as number] as TItem;
|
||||
const actualStatus = itemList.status;
|
||||
const newItemList = {
|
||||
...itemList,
|
||||
status: actualStatus === Status.TODO ? Status.DONE : Status.TODO
|
||||
};
|
||||
const newList = [
|
||||
...state.list.slice(0, action.payload.index as number),
|
||||
newItemList,
|
||||
...state.list.slice(action.payload.index as number + 1)
|
||||
];
|
||||
return {
|
||||
list: newList
|
||||
};
|
||||
}
|
||||
case ActionTypesList.DeleteItem: {
|
||||
const newList = [
|
||||
...state.list.slice(0, action.payload.index as number),
|
||||
...state.list.slice(action.payload.index as number + 1)
|
||||
];
|
||||
return {
|
||||
list: newList
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default listReducer;
|
@ -1,20 +0,0 @@
|
||||
import { TAction } from '../actions';
|
||||
|
||||
const initialState = {
|
||||
hello: 'world'
|
||||
};
|
||||
|
||||
const testReducer = (state = initialState, action: TAction) => {
|
||||
switch (action.type){
|
||||
case 'CHANGE_HELLO': {
|
||||
const newHello = action.payload.hello;
|
||||
return {
|
||||
hello: newHello
|
||||
};
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default testReducer;
|
@ -1,4 +1,4 @@
|
||||
$base-color: #282c34;
|
||||
$base-color: #FFFFFF;
|
||||
|
||||
body {
|
||||
background-color: $base-color;
|
||||
|
@ -1,15 +1,9 @@
|
||||
import React from 'react';
|
||||
import InitialComponent from '../frontend/components/InitialComponent';
|
||||
import OtherComponent from '../frontend/components/OtherComponent';
|
||||
|
||||
const OTHER_COMPONENT = {
|
||||
path: '/other-component',
|
||||
element: <OtherComponent />
|
||||
};
|
||||
import List from '../frontend/components/List';
|
||||
|
||||
const INITIAL_COMPONENT = {
|
||||
path: '/',
|
||||
element: <InitialComponent />,
|
||||
element: <List />,
|
||||
};
|
||||
|
||||
export default [ INITIAL_COMPONENT, OTHER_COMPONENT ];
|
||||
export default [ INITIAL_COMPONENT ];
|
||||
|
@ -43,7 +43,7 @@ func RegisterHandlers(e *echo.Echo, paths []string) {
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!-- ${manifestJson} -->
|
||||
<link href="assets/frontend.css" rel="stylesheet" type="text/css"></link>
|
||||
|
||||
<link href="assets/vendors.css" rel="stylesheet" type="text/css"></link>
|
||||
<title>App</title>
|
||||
</head>
|
||||
<body>
|
||||
|
Loading…
Reference in New Issue
Block a user