Skip to content
This repository was archived by the owner on Oct 12, 2019. It is now read-only.

Commit 32c02c8

Browse files
Merge pull request #103 from ecatch-kyst/develop
🔖release/1.0.0-beta5
2 parents 993d84a + 04f7f9b commit 32c02c8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2272
-2130
lines changed

CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file.
33

44
## Unreleased
55

6+
## [1.0.0-beta5] - 2019-04-08
7+
### Changed
8+
- notification, dialogs, dropdowns moved to their own namespaces in `locales` ([#57](https://github.com/ecatch-kyst/web/issues/57))
9+
- dashboard -> homepage ([#57](https://github.com/ecatch-kyst/web/issues/57))
10+
- DCA is split into two parts ([#93](https://github.com/ecatch-kyst/web/issues/93))
11+
12+
### Added
13+
- preset for making favorites groups in dropdown ([#99](https://github.com/ecatch-kyst/web/issues/99))
14+
- page on "homescreen" for setting the preset
15+
- input validation ([#90](https://github.com/ecatch-kyst/web/issues/90))
16+
17+
### Removed
18+
- unused translations ([#57](https://github.com/ecatch-kyst/web/issues/57))
19+
- delete option
20+
21+
### Fixed
22+
- DU field is now calculated from fishingStart and fishingEnd
23+
24+
625
## [1.0.0-beta4] - 2019-03-25
726
### Changed
827
- New Logo
@@ -15,7 +34,7 @@ All notable changes to this project will be documented in this file.
1534

1635
### Added
1736
- Assets for Android, iOS, macOS Safari, Windows
18-
- WIP: 🚧 Preset values ([#52](https://github.com/ecatch-kyst/web/issues/22))
37+
- WIP: 🚧 Preset values ([#52](https://github.com/ecatch-kyst/web/issues/52))
1938
- User can now add his own fishingSpots. ([#52](https://github.com/ecatch-kyst/web/issues/52))
2039
- date format interpolation to i18n (show dates differently for different languages)
2140
- Trips view

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "web",
33
"license": "GPL",
4-
"version": "1.0.0-beta4",
4+
"version": "1.0.0-beta5",
55
"private": true,
66
"dependencies": {
77
"@material-ui/core": "^3.9.3",

src/App.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {Route, Switch, withRouter, Link} from "react-router-dom"
44
import ProfileIcon from "@material-ui/icons/PersonOutlineOutlined"
55
import DashboardIcon from "@material-ui/icons/DashboardOutlined"
66
import TripIcon from "@material-ui/icons/CompareArrowsOutlined"
7+
import PresetIcon from "@material-ui/icons/AddSharp"
78

89
import {withTheme, BottomNavigation, BottomNavigationAction} from '@material-ui/core'
910

@@ -14,16 +15,18 @@ import {
1415
Profile,
1516
Register,
1617
OfflineStatus,
17-
Dashboard,
18+
HomePage,
1819
NotFound,
1920
Dialog,
2021
Trips,
2122
Messages,
2223
Trip,
2324
EditCatch,
2425
Form,
25-
Notification
26+
Notification,
27+
Preset
2628
} from './components'
29+
2730
import {useTranslation} from 'react-i18next'
2831

2932

@@ -33,7 +36,8 @@ export const App = ({theme: {palette: {type}}}) =>
3336
<Route component={Landing} exact path={routes.ROOT}/>
3437
<Route component={Register} exact path={routes.REGISTER}/>
3538
<Route component={Profile} exact path={routes.PROFILE}/>
36-
<Route component={Dashboard} exact path={routes.DASHBOARD}/>
39+
<Route component={HomePage} exact path={routes.HOMEPAGE}/>
40+
<Route component={Preset} exact path={routes.PRESET}/>
3741
<Route component={Trips} exact path={routes.TRIPS}/>
3842
<Route component={Trip} exact path={`${routes.TRIPS}/:tripId`}/>
3943
<Route component={Messages} exact path={routes.MESSAGES}/>
@@ -60,9 +64,9 @@ export default withRouter(withTheme()(App))
6064

6165
const navigation = [
6266
{
63-
id: "dashboard",
67+
id: "homepage",
6468
icon: <DashboardIcon/>,
65-
to: routes.DASHBOARD
69+
to: routes.HOMEPAGE
6670
},
6771
{
6872
id: "trips",
@@ -73,6 +77,11 @@ const navigation = [
7377
id: "profile",
7478
icon: <ProfileIcon/>,
7579
to: routes.PROFILE
80+
},
81+
{
82+
id: "preset",
83+
icon: <PresetIcon/>,
84+
to: routes.PRESET
7685
}
7786
]
7887

src/components/Forms/Form.jsx

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {useEffect, useState} from 'react'
22

3-
import {Link, Redirect, withRouter} from "react-router-dom"
3+
import {Link, withRouter} from "react-router-dom"
44
import forms from "./forms.json"
55
import {Grid, Button, Divider, Typography} from '@material-ui/core'
66
import {routes} from '../../lib/router.js'
@@ -9,9 +9,8 @@ import {Page} from '../shared'
99

1010
import FormInput from './FormInput.jsx'
1111
import {useStore} from '../../hooks'
12-
import {addHours} from 'date-fns'
12+
import {addHours, format} from 'date-fns'
1313

14-
import initialValues from "../../db/initialValues.json"
1514

1615
/**
1716
* Form component
@@ -21,28 +20,27 @@ import initialValues from "../../db/initialValues.json"
2120
* @param {'DEP'|'DCA'|'POR'} props.match.params.type - Type of form
2221
* @param {number} props.match.params.messageId - id of message if form is used for editing
2322
*/
24-
export const Form = ({match: {path, params: {type, messageId}}}) => {
25-
const {fields, isEnRoute, handleFieldChange, messages, position, handleDialog, submitMessage} = useStore()
23+
export const Form = ({history, match: {path, params: {type, /*messageId*/}}}) => {
24+
const {fields, handleFieldChange, messages, position, handleDialog, submitMessage, trips, toggleDCAStart} = useStore()
2625
const [t] = useTranslation("forms")
2726

28-
const [canEdit, setCanEdit] = useState(false)
27+
// const [setCanEdit] = useState(false)
2928
const [baseMessage, setBaseMessage] = useState({})
3029

3130
const [validType, setValidType] = useState(false)
3231

3332

3433
useEffect(() => {
35-
setCanEdit(messageId && type === "DCA"&& messages.find(m => m.TM === "DCA" && m.RN === parseInt(messageId, 10)))
3634
const newValidType = Object.keys(forms).includes(type)
3735
setValidType(newValidType)
3836
if (newValidType)
3937
setBaseMessage(messages.find(m => m.TM === type) || {})
40-
}, [type, messageId])
38+
}, [])
4139

4240

4341
useEffect(() => {
4442
if(!validType) return
45-
let newFields = {...initialValues.fields} // Start with empty fields, to prevent rogue values.
43+
let newFields = {}//{...initialValues.fields} // Start with empty fields, to prevent rogue values.
4644
const now = new Date()
4745
switch (type) {
4846
case "DEP":
@@ -63,11 +61,27 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
6361
}
6462
break
6563

66-
case "DCA":
64+
case "DCA0":
6765
newFields = { // These values will be preset, no matter if there is a base message.
6866
...newFields,
6967
fishingStart: now,
70-
expectedFishingStart: addHours(now, 2)
68+
startFishingSpot: position,
69+
GE: "DRB"
70+
}
71+
if (Object.keys(baseMessage).length) {
72+
newFields = { // Preset from base (previous message, with the same type)
73+
...newFields,
74+
AC: baseMessage.AC,
75+
GS: baseMessage.GS,
76+
QI: baseMessage.QI
77+
}
78+
}
79+
break
80+
case "DCA":
81+
newFields = { // These values will be preset, no matter if there is a base message.
82+
...newFields,
83+
endFishingSpot: position,
84+
DU: fields.fishingStart ? parseInt(format(Date.now() - new Date(fields.fishingStart).getTime(), "m"), 10) : 0
7185
}
7286
if (Object.keys(baseMessage).length) {
7387
newFields = { // Preset from base (previous message, with the same type)
@@ -79,10 +93,7 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
7993
CA: baseMessage.CA,
8094
GE: baseMessage.GE,
8195
GS: baseMessage.GS,
82-
DU: baseMessage.DU,
83-
QI: baseMessage.QI,
84-
startFishingSpot: position,
85-
endFishingSpot: baseMessage.endFishingSpot
96+
QI: baseMessage.QI
8697
}
8798
}
8899
break
@@ -92,11 +103,19 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
92103
portArrival: now // NOTE: try to calculate from position, speed and PO (port)
93104
}
94105
if (Object.keys(baseMessage).length) {
106+
const activeTrip = trips.find(t => !t.isFinished)
107+
const sum = activeTrip ? activeTrip.DCAList.reduce((acc, d) => {
108+
Object.entries(d.CA).forEach(([type, weight]) => {
109+
acc[type] ? acc[type] += weight : acc[type] = weight
110+
})
111+
return acc
112+
}, {}) : {}
113+
95114
newFields = { // Preset from base (previous message, with the same type)
96115
...newFields,
97-
KG: baseMessage.KG,
116+
KG: sum,
98117
LS: baseMessage.LS,
99-
OB: baseMessage.OB,
118+
OB: sum,
100119
PO: baseMessage.PO
101120
}
102121
}
@@ -116,7 +135,7 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
116135

117136
// /** REVIEW: When this componentDidMount is called,
118137
// * messages is probably still empty,
119-
// * if the user opens the form in a new tab, instead of coming from the dashboard.
138+
// * if the user opens the form in a new tab, instead of coming from the homepage.
120139
// */
121140

122141
// const now = new Date()
@@ -186,18 +205,22 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
186205
*/
187206
const handleSubmit = e => {
188207
e.preventDefault()
208+
if (type === "DCA0") {
209+
toggleDCAStart(true)
210+
history.push(routes.DASHBOARD)
211+
return
212+
}
189213
handleDialog({type, submit: () => submitMessage(type)})
190214
}
191215

192216
const form = forms[type] // Extract form from forms.json
193217

194-
const isAllowed = (isEnRoute ? ["DCA", "POR"].includes(type) : type === "DEP") || (canEdit && type === "DCA")
195218

196219
return (
197220
<Page style={{marginBottom: 64}} title={t(`${type}.title`)}>
198221
<Grid alignItems="center" container direction="column" spacing={16}>
199222
<Grid component="form" item onSubmit={handleSubmit}>
200-
{isAllowed ? form.map(({id, step}) => // If a valid form, iterate over its steps
223+
{form.map(({id, step}) => // If a valid form, iterate over its steps
201224
<Grid container direction="column" key={id} spacing={16} style={{paddingBottom: 32}}>
202225
<Grid component={Typography} item variant="subtitle2" xs={12}>{t(`${type}.steps.${id}`)}</Grid>
203226
{step.map(({id, dataId, type, dependent, options={}}) => // Iterate over all the input fields in a Form step
@@ -217,8 +240,7 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
217240
)}
218241
<Divider style={{marginTop: 16}}/>
219242
</Grid>
220-
) :
221-
<Redirect to={routes.DASHBOARD}/> // If the form is invalid, redirect to the dashboard
243+
)
222244
}
223245
</Grid>
224246
<Grid container item justify="center">
@@ -227,7 +249,7 @@ export const Form = ({match: {path, params: {type, messageId}}}) => {
227249
color="secondary"
228250
component={Link}
229251
size="large"
230-
to={routes.DASHBOARD}
252+
to={routes.HOMEPAGE}
231253
>
232254
{t("links.back")}
233255
</Button>

src/components/Forms/FormInput.jsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TextInput from './components/TextInput'
66
import DropdownMap from './components/DropdownMap'
77
import GeoPointInput from './components/GeoPointInput'
88
import {useStore} from '../../hooks'
9+
import {validate} from '../../utils'
910

1011
/**
1112
* Dynamic input field
@@ -18,25 +19,30 @@ import {useStore} from '../../hooks'
1819

1920
export const FormInput = ({id, dataId, type, options}) => {
2021

21-
const {handleFieldChange, fields} = useStore()
22+
const {handleFieldChange, fields, handleFieldError, errors, notify} = useStore()
2223
const [t] = useTranslation("forms")
2324

24-
const handleChange = (name, value) => {
25-
const error = null // TODO: validate[dataId](value) // Validating the field
25+
const handleChange = ({name, value}) => {
26+
const {error, reason} = validate(name, value) // Validating the field
27+
handleFieldError(name, error)
2628
if (error) {
27-
console.error(error) // TODO: Add error notification
29+
notify({name: `fields.${reason}`, type: "error"})
2830
} else {
31+
handleFieldError(name, false)
2932
handleFieldChange(name, value)
3033
}
3134
}
3235

3336
const value = fields[id || dataId]
37+
const error = errors[id || dataId]
3438

3539
const common = {
3640
onChange: handleChange,
37-
label: t(`labels.${id}`),
41+
label:t(`labels.${id}`),
42+
// TODO: Add custom error labels //label: error ? t(`errors.${id}`) : t(`labels.${id}`),
3843
placeholder: t(`labels.${id}`),
3944
value,
45+
error,
4046
disabled: !options.editable
4147
}
4248

src/components/Forms/components/AddFishingSpot.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import TextInput from './TextInput'
88
import {useStore} from '../../../hooks'
99

1010
export const AddFishingSpot = () => {
11-
const [t] = useTranslation("forms")
11+
const [t] = useTranslation("dropdowns")
1212
const {
1313
handleDialog,
1414
handleCustomListChange,
@@ -29,15 +29,15 @@ export const AddFishingSpot = () => {
2929
autoFocus
3030
dataId="label"
3131
fullWidth
32-
label={t("dropdowns.customLists.fishingSpots.label")}
32+
label={t("customLists.fishingSpots.label")}
3333
onChange={handleCustomListChange}
3434
value={label}
3535
/>
3636
</Grid>
3737
<Grid container direction="column" item justify="center">
3838
<GeoPointInput
3939
dataId="value"
40-
// label={t("dropdowns.customLists.fishingSpots.coordinates")}
40+
// label={t("customLists.fishingSpots.coordinates")}
4141
onChange={handleCustomListChange}
4242
value={value}
4343
/>
@@ -46,7 +46,7 @@ export const AddFishingSpot = () => {
4646
})
4747
}
4848
variant="text"
49-
>{t("dropdowns.customLists.fishingSpots.button")}
49+
>{t("customLists.fishingSpots.button")}
5050
</Button>
5151
)
5252
}

0 commit comments

Comments
 (0)