create-foldkit-app 0.29.0 → 0.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/templates/base/AGENTS.md +5 -112
- package/dist/templates/base/FOLDKIT.md +144 -0
- package/dist/templates/examples/api-cache/src/main.ts +36 -40
- package/dist/templates/examples/auth/src/main.ts +16 -15
- package/dist/templates/examples/auth/src/page/loggedIn/update.ts +10 -11
- package/dist/templates/examples/auth/src/page/loggedOut/page/login.ts +44 -55
- package/dist/templates/examples/auth/src/page/loggedOut/update.ts +8 -12
- package/dist/templates/examples/auth/src/update.ts +67 -73
- package/dist/templates/examples/canvas-art/src/main.ts +32 -31
- package/dist/templates/examples/charting/src/init.test.ts +6 -3
- package/dist/templates/examples/charting/src/init.ts +4 -4
- package/dist/templates/examples/charting/src/update.ts +34 -38
- package/dist/templates/examples/counter/src/main.ts +13 -13
- package/dist/templates/examples/counters/src/counter.ts +9 -8
- package/dist/templates/examples/counters/src/main.ts +20 -26
- package/dist/templates/examples/crash-view/src/main.ts +5 -3
- package/dist/templates/examples/embedding/src/main.ts +11 -9
- package/dist/templates/examples/form/src/main.ts +79 -89
- package/dist/templates/examples/generative-art/src/main.ts +6 -4
- package/dist/templates/examples/generative-art/src/update.ts +26 -23
- package/dist/templates/examples/interrupting-commands/src/main.ts +68 -66
- package/dist/templates/examples/job-application/src/main.ts +3 -4
- package/dist/templates/examples/job-application/src/step/attachments.ts +16 -19
- package/dist/templates/examples/job-application/src/step/coverLetter.ts +5 -5
- package/dist/templates/examples/job-application/src/step/education/education.ts +12 -17
- package/dist/templates/examples/job-application/src/step/education/entry.ts +29 -42
- package/dist/templates/examples/job-application/src/step/personalInfo.ts +35 -44
- package/dist/templates/examples/job-application/src/step/skills/entry.ts +15 -21
- package/dist/templates/examples/job-application/src/step/skills/skills.ts +12 -17
- package/dist/templates/examples/job-application/src/step/workHistory/entry.ts +41 -58
- package/dist/templates/examples/job-application/src/step/workHistory/workHistory.ts +12 -17
- package/dist/templates/examples/job-application/src/update.ts +26 -29
- package/dist/templates/examples/kanban/src/main.ts +3 -4
- package/dist/templates/examples/kanban/src/update.ts +31 -31
- package/dist/templates/examples/managed-resource-layer/src/main.ts +30 -34
- package/dist/templates/examples/map/src/main.ts +48 -56
- package/dist/templates/examples/pixel-art/src/comparison.bench.test.ts +34 -13
- package/dist/templates/examples/pixel-art/src/main.bench.ts +3 -3
- package/dist/templates/examples/pixel-art/src/main.ts +3 -4
- package/dist/templates/examples/pixel-art/src/update.ts +109 -100
- package/dist/templates/examples/query-sync/src/main.ts +27 -25
- package/dist/templates/examples/route-transitions/src/main.ts +46 -43
- package/dist/templates/examples/route-transitions/src/story.test.ts +11 -11
- package/dist/templates/examples/routing/src/main.ts +16 -14
- package/dist/templates/examples/routing/src/page/people.ts +23 -28
- package/dist/templates/examples/shopping-cart/src/main.ts +41 -42
- package/dist/templates/examples/shopping-cart/src/page/products.ts +28 -35
- package/dist/templates/examples/slow-warnings/src/main.ts +23 -32
- package/dist/templates/examples/snake/src/main.ts +135 -143
- package/dist/templates/examples/ssg/src/main.ts +20 -17
- package/dist/templates/examples/ssr/src/main.ts +20 -24
- package/dist/templates/examples/state-machine/src/main.ts +24 -11
- package/dist/templates/examples/state-machine/src/story.test.ts +2 -2
- package/dist/templates/examples/stopwatch/src/main.ts +42 -50
- package/dist/templates/examples/todo/src/main.ts +152 -160
- package/dist/templates/examples/ui-showcase/src/main.ts +53 -54
- package/dist/templates/examples/ui-showcase/src/scene.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/story.test.ts +2 -2
- package/dist/templates/examples/ui-showcase/src/ui/init.ts +6 -7
- package/dist/templates/examples/ui-showcase/src/ui/update.ts +265 -336
- package/dist/templates/examples/view-transitions/src/main.ts +18 -17
- package/dist/templates/examples/weather/src/main.ts +33 -40
- package/dist/templates/examples/web-components/src/main.ts +14 -17
- package/dist/templates/examples/websocket-chat/src/main.ts +44 -50
- package/dist/templates/release.json +8 -8
- package/dist/templates/rendering/ssg/src/main.ts +20 -17
- package/dist/templates/rendering/ssr/src/main.ts +20 -24
- package/package.json +1 -1
|
@@ -54,20 +54,17 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
54
54
|
|
|
55
55
|
// UPDATE
|
|
56
56
|
|
|
57
|
-
type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
|
|
58
|
-
|
|
59
57
|
const foldEntryOutMessage: (
|
|
60
58
|
entryId: string,
|
|
61
59
|
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
62
60
|
M.type<Entry.OutMessage>().pipe(
|
|
63
61
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
64
62
|
M.tagsExhaustive({
|
|
65
|
-
Removed: () => model =>
|
|
66
|
-
evo(model, {
|
|
63
|
+
Removed: () => model => ({
|
|
64
|
+
model: evo(model, {
|
|
67
65
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
68
66
|
}),
|
|
69
|
-
|
|
70
|
-
],
|
|
67
|
+
}),
|
|
71
68
|
}),
|
|
72
69
|
)
|
|
73
70
|
|
|
@@ -85,24 +82,22 @@ const foldEntry = (entryId: string) =>
|
|
|
85
82
|
})
|
|
86
83
|
|
|
87
84
|
export const update = (model: Model, message: Message) =>
|
|
88
|
-
Message.match<
|
|
89
|
-
ClickedAddEntry: () =>
|
|
85
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
86
|
+
ClickedAddEntry: () => ({ model, commands: [GenerateEntryId()] }),
|
|
90
87
|
|
|
91
|
-
SucceededGenerateEntryId: ({ entryId }) =>
|
|
92
|
-
evo(model, {
|
|
88
|
+
SucceededGenerateEntryId: ({ entryId }) => ({
|
|
89
|
+
model: evo(model, {
|
|
93
90
|
entries: Array.append(Entry.init(entryId)),
|
|
94
91
|
}),
|
|
95
|
-
|
|
96
|
-
],
|
|
92
|
+
}),
|
|
97
93
|
|
|
98
|
-
FailedGenerateEntryId: () =>
|
|
94
|
+
FailedGenerateEntryId: () => ({ model }),
|
|
99
95
|
|
|
100
|
-
RemovedEntry: ({ entryId }) =>
|
|
101
|
-
evo(model, {
|
|
96
|
+
RemovedEntry: ({ entryId }) => ({
|
|
97
|
+
model: evo(model, {
|
|
102
98
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
103
99
|
}),
|
|
104
|
-
|
|
105
|
-
],
|
|
100
|
+
}),
|
|
106
101
|
|
|
107
102
|
GotEntryMessage: ({ entryId, message }) =>
|
|
108
103
|
foldEntry(entryId)(model, message),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Match as M, Option, Schema as S } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Update } from 'foldkit'
|
|
3
3
|
import {
|
|
4
4
|
Field,
|
|
5
5
|
NotValidated,
|
|
@@ -87,21 +87,14 @@ export const init = (entryId: string): Model => ({
|
|
|
87
87
|
|
|
88
88
|
// UPDATE
|
|
89
89
|
|
|
90
|
-
type UpdateReturn = readonly [
|
|
91
|
-
Model,
|
|
92
|
-
ReadonlyArray<Command.Command<Message>>,
|
|
93
|
-
Option.Option<OutMessage>,
|
|
94
|
-
]
|
|
95
|
-
|
|
96
90
|
const foldGraduationYearListboxOutMessage = M.type<Listbox.OutMessage>().pipe(
|
|
97
91
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
98
92
|
M.tagsExhaustive({
|
|
99
93
|
Selected:
|
|
100
94
|
({ value }) =>
|
|
101
|
-
model =>
|
|
102
|
-
evo(model, { maybeGraduationYear: () => Option.some(value) }),
|
|
103
|
-
|
|
104
|
-
],
|
|
95
|
+
model => ({
|
|
96
|
+
model: evo(model, { maybeGraduationYear: () => Option.some(value) }),
|
|
97
|
+
}),
|
|
105
98
|
}),
|
|
106
99
|
)
|
|
107
100
|
|
|
@@ -112,41 +105,35 @@ const foldGraduationYearListbox = Update.foldChild({
|
|
|
112
105
|
evo(model, { graduationYearListbox: () => nextGraduationYearListbox }),
|
|
113
106
|
toParentMessage: message =>
|
|
114
107
|
Message.GotGraduationYearListboxMessage({ message }),
|
|
115
|
-
toParentOutMessage: () => Option.none(),
|
|
116
108
|
foldOutMessage: foldGraduationYearListboxOutMessage,
|
|
117
109
|
})
|
|
118
110
|
|
|
119
111
|
export const update = (model: Model, message: Message) =>
|
|
120
|
-
Message.match<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
Option.none(),
|
|
146
|
-
],
|
|
147
|
-
|
|
148
|
-
ClickedRemoveSelf: () => [model, [], Option.some(OutMessage.Removed())],
|
|
149
|
-
})
|
|
112
|
+
Message.match<Update.ReturnWithOutMessage<Model, Message, OutMessage>>(
|
|
113
|
+
message,
|
|
114
|
+
{
|
|
115
|
+
UpdatedSchool: ({ value }) => ({
|
|
116
|
+
model: evo(model, { school: () => validateSchool(value) }),
|
|
117
|
+
}),
|
|
118
|
+
|
|
119
|
+
UpdatedDegree: ({ value }) => ({
|
|
120
|
+
model: evo(model, { degree: () => validateDegree(value) }),
|
|
121
|
+
}),
|
|
122
|
+
|
|
123
|
+
UpdatedFieldOfStudy: ({ value }) => ({
|
|
124
|
+
model: evo(model, { fieldOfStudy: () => validateFieldOfStudy(value) }),
|
|
125
|
+
}),
|
|
126
|
+
|
|
127
|
+
GotGraduationYearListboxMessage: ({ message }) =>
|
|
128
|
+
foldGraduationYearListbox(model, message),
|
|
129
|
+
|
|
130
|
+
ToggledCurrentlyEnrolled: ({ isChecked }) => ({
|
|
131
|
+
model: evo(model, { isCurrentlyEnrolled: () => isChecked }),
|
|
132
|
+
}),
|
|
133
|
+
|
|
134
|
+
ClickedRemoveSelf: () => ({ model, outMessage: OutMessage.Removed() }),
|
|
135
|
+
},
|
|
136
|
+
)
|
|
150
137
|
|
|
151
138
|
// VALIDATION SUMMARY
|
|
152
139
|
|
|
@@ -162,17 +162,16 @@ export const ValidateEmailAsync = Command.define('ValidateEmailAsync', {
|
|
|
162
162
|
|
|
163
163
|
// UPDATE
|
|
164
164
|
|
|
165
|
-
type UpdateReturn =
|
|
165
|
+
type UpdateReturn = Update.Return<Model, Message>
|
|
166
166
|
|
|
167
167
|
const foldPronounsOutMessage = M.type<Listbox.OutMessage>().pipe(
|
|
168
168
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
169
169
|
M.tagsExhaustive({
|
|
170
170
|
Selected:
|
|
171
171
|
({ value }) =>
|
|
172
|
-
model =>
|
|
173
|
-
evo(model, { maybeSelectedPronoun: () => Option.some(value) }),
|
|
174
|
-
|
|
175
|
-
],
|
|
172
|
+
model => ({
|
|
173
|
+
model: evo(model, { maybeSelectedPronoun: () => Option.some(value) }),
|
|
174
|
+
}),
|
|
176
175
|
}),
|
|
177
176
|
)
|
|
178
177
|
|
|
@@ -189,15 +188,13 @@ const foldAvailableDateOutMessage = M.type<DatePicker.OutMessage>().pipe(
|
|
|
189
188
|
M.tagsExhaustive({
|
|
190
189
|
SelectedDate:
|
|
191
190
|
({ date }) =>
|
|
192
|
-
model =>
|
|
193
|
-
evo(model, { maybeAvailableDate: () => Option.some(date) }),
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
],
|
|
200
|
-
ChangedViewMonth: () => model => [model, []],
|
|
191
|
+
model => ({
|
|
192
|
+
model: evo(model, { maybeAvailableDate: () => Option.some(date) }),
|
|
193
|
+
}),
|
|
194
|
+
ClearedDate: () => model => ({
|
|
195
|
+
model: evo(model, { maybeAvailableDate: () => Option.none() }),
|
|
196
|
+
}),
|
|
197
|
+
ChangedViewMonth: () => model => ({ model }),
|
|
201
198
|
}),
|
|
202
199
|
)
|
|
203
200
|
|
|
@@ -212,63 +209,57 @@ const foldAvailableDate = Update.foldChild({
|
|
|
212
209
|
|
|
213
210
|
export const update = (model: Model, message: Message) =>
|
|
214
211
|
Message.match<UpdateReturn>(message, {
|
|
215
|
-
UpdatedFirstName: ({ value }) =>
|
|
216
|
-
evo(model, { firstName: () => validateFirstName(value) }),
|
|
217
|
-
|
|
218
|
-
],
|
|
212
|
+
UpdatedFirstName: ({ value }) => ({
|
|
213
|
+
model: evo(model, { firstName: () => validateFirstName(value) }),
|
|
214
|
+
}),
|
|
219
215
|
|
|
220
|
-
UpdatedLastName: ({ value }) =>
|
|
221
|
-
evo(model, { lastName: () => validateLastName(value) }),
|
|
222
|
-
|
|
223
|
-
],
|
|
216
|
+
UpdatedLastName: ({ value }) => ({
|
|
217
|
+
model: evo(model, { lastName: () => validateLastName(value) }),
|
|
218
|
+
}),
|
|
224
219
|
|
|
225
220
|
UpdatedEmail: ({ value }) => {
|
|
226
221
|
const validationId = Number.increment(model.emailValidationId)
|
|
227
222
|
return M.value(validateEmail(value)).pipe(
|
|
228
223
|
M.withReturnType<UpdateReturn>(),
|
|
229
|
-
M.tag('Valid', () =>
|
|
230
|
-
evo(model, {
|
|
224
|
+
M.tag('Valid', () => ({
|
|
225
|
+
model: evo(model, {
|
|
231
226
|
email: () => Validating({ value }),
|
|
232
227
|
emailValidationId: () => validationId,
|
|
233
228
|
}),
|
|
234
|
-
[ValidateEmailAsync({ emailInput: value, validationId })],
|
|
235
|
-
|
|
236
|
-
M.orElse(syncResult =>
|
|
237
|
-
evo(model, {
|
|
229
|
+
commands: [ValidateEmailAsync({ emailInput: value, validationId })],
|
|
230
|
+
})),
|
|
231
|
+
M.orElse(syncResult => ({
|
|
232
|
+
model: evo(model, {
|
|
238
233
|
email: () => syncResult,
|
|
239
234
|
emailValidationId: () => validationId,
|
|
240
235
|
}),
|
|
241
|
-
|
|
242
|
-
]),
|
|
236
|
+
})),
|
|
243
237
|
)
|
|
244
238
|
},
|
|
245
239
|
|
|
246
240
|
CompletedValidateEmailAsync: ({ validationId, field }) => {
|
|
247
241
|
if (validationId === model.emailValidationId) {
|
|
248
|
-
return
|
|
242
|
+
return { model: evo(model, { email: () => field }) }
|
|
249
243
|
} else {
|
|
250
|
-
return
|
|
244
|
+
return { model }
|
|
251
245
|
}
|
|
252
246
|
},
|
|
253
247
|
|
|
254
|
-
UpdatedPhone: ({ value }) =>
|
|
255
|
-
evo(model, { phone: () => validatePhone(value) }),
|
|
256
|
-
|
|
257
|
-
],
|
|
248
|
+
UpdatedPhone: ({ value }) => ({
|
|
249
|
+
model: evo(model, { phone: () => validatePhone(value) }),
|
|
250
|
+
}),
|
|
258
251
|
|
|
259
252
|
GotPronounsMessage: ({ message }) => foldPronouns(model, message),
|
|
260
253
|
|
|
261
|
-
UpdatedCustomPronouns: ({ value }) =>
|
|
262
|
-
evo(model, { customPronouns: () => value }),
|
|
263
|
-
|
|
264
|
-
],
|
|
254
|
+
UpdatedCustomPronouns: ({ value }) => ({
|
|
255
|
+
model: evo(model, { customPronouns: () => value }),
|
|
256
|
+
}),
|
|
265
257
|
|
|
266
|
-
UpdatedPortfolioUrl: ({ value }) =>
|
|
267
|
-
evo(model, {
|
|
258
|
+
UpdatedPortfolioUrl: ({ value }) => ({
|
|
259
|
+
model: evo(model, {
|
|
268
260
|
portfolioUrl: () => validatePortfolioUrl(value),
|
|
269
261
|
}),
|
|
270
|
-
|
|
271
|
-
],
|
|
262
|
+
}),
|
|
272
263
|
|
|
273
264
|
GotAvailableDateMessage: ({ message }) => foldAvailableDate(model, message),
|
|
274
265
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Match as M, Option, Schema as S } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Update } from 'foldkit'
|
|
3
3
|
import {
|
|
4
4
|
Field,
|
|
5
5
|
NotValidated,
|
|
@@ -73,12 +73,6 @@ export const init = (entryId: string): Model => ({
|
|
|
73
73
|
|
|
74
74
|
// UPDATE
|
|
75
75
|
|
|
76
|
-
type UpdateReturn = readonly [
|
|
77
|
-
Model,
|
|
78
|
-
ReadonlyArray<Command.Command<Message>>,
|
|
79
|
-
Option.Option<OutMessage>,
|
|
80
|
-
]
|
|
81
|
-
|
|
82
76
|
const foldProficiencyRadioGroupOutMessage = M.type<
|
|
83
77
|
RadioGroup.OutMessage<ProficiencyLevel.ProficiencyLevel>
|
|
84
78
|
>().pipe(
|
|
@@ -86,7 +80,7 @@ const foldProficiencyRadioGroupOutMessage = M.type<
|
|
|
86
80
|
M.tagsExhaustive({
|
|
87
81
|
Selected:
|
|
88
82
|
({ value }) =>
|
|
89
|
-
model =>
|
|
83
|
+
model => ({ model: evo(model, { proficiency: () => value }) }),
|
|
90
84
|
}),
|
|
91
85
|
)
|
|
92
86
|
|
|
@@ -98,22 +92,22 @@ const foldProficiencyRadioGroup = Update.foldChild({
|
|
|
98
92
|
toParentMessage: message =>
|
|
99
93
|
Message.GotProficiencyRadioGroupMessage({ message }),
|
|
100
94
|
foldOutMessage: foldProficiencyRadioGroupOutMessage,
|
|
101
|
-
toParentOutMessage: () => Option.none(),
|
|
102
95
|
})
|
|
103
96
|
|
|
104
97
|
export const update = (model: Model, message: Message) =>
|
|
105
|
-
Message.match<
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
98
|
+
Message.match<Update.ReturnWithOutMessage<Model, Message, OutMessage>>(
|
|
99
|
+
message,
|
|
100
|
+
{
|
|
101
|
+
UpdatedName: ({ value }) => ({
|
|
102
|
+
model: evo(model, { name: () => validateName(value) }),
|
|
103
|
+
}),
|
|
104
|
+
|
|
105
|
+
GotProficiencyRadioGroupMessage: ({ message }) =>
|
|
106
|
+
foldProficiencyRadioGroup(model, message),
|
|
107
|
+
|
|
108
|
+
ClickedRemoveSelf: () => ({ model, outMessage: OutMessage.Removed() }),
|
|
109
|
+
},
|
|
110
|
+
)
|
|
117
111
|
|
|
118
112
|
// VALIDATION SUMMARY
|
|
119
113
|
|
|
@@ -51,20 +51,17 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
51
51
|
|
|
52
52
|
// UPDATE
|
|
53
53
|
|
|
54
|
-
type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
|
|
55
|
-
|
|
56
54
|
const foldEntryOutMessage: (
|
|
57
55
|
entryId: string,
|
|
58
56
|
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
59
57
|
M.type<Entry.OutMessage>().pipe(
|
|
60
58
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
61
59
|
M.tagsExhaustive({
|
|
62
|
-
Removed: () => model =>
|
|
63
|
-
evo(model, {
|
|
60
|
+
Removed: () => model => ({
|
|
61
|
+
model: evo(model, {
|
|
64
62
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
65
63
|
}),
|
|
66
|
-
|
|
67
|
-
],
|
|
64
|
+
}),
|
|
68
65
|
}),
|
|
69
66
|
)
|
|
70
67
|
|
|
@@ -82,24 +79,22 @@ const foldEntry = (entryId: string) =>
|
|
|
82
79
|
})
|
|
83
80
|
|
|
84
81
|
export const update = (model: Model, message: Message) =>
|
|
85
|
-
Message.match<
|
|
86
|
-
ClickedAddEntry: () =>
|
|
82
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
83
|
+
ClickedAddEntry: () => ({ model, commands: [GenerateEntryId()] }),
|
|
87
84
|
|
|
88
|
-
SucceededGenerateEntryId: ({ entryId }) =>
|
|
89
|
-
evo(model, {
|
|
85
|
+
SucceededGenerateEntryId: ({ entryId }) => ({
|
|
86
|
+
model: evo(model, {
|
|
90
87
|
entries: Array.append(Entry.init(entryId)),
|
|
91
88
|
}),
|
|
92
|
-
|
|
93
|
-
],
|
|
89
|
+
}),
|
|
94
90
|
|
|
95
|
-
FailedGenerateEntryId: () =>
|
|
91
|
+
FailedGenerateEntryId: () => ({ model }),
|
|
96
92
|
|
|
97
|
-
RemovedEntry: ({ entryId }) =>
|
|
98
|
-
evo(model, {
|
|
93
|
+
RemovedEntry: ({ entryId }) => ({
|
|
94
|
+
model: evo(model, {
|
|
99
95
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
100
96
|
}),
|
|
101
|
-
|
|
102
|
-
],
|
|
97
|
+
}),
|
|
103
98
|
|
|
104
99
|
GotEntryMessage: ({ entryId, message }) =>
|
|
105
100
|
foldEntry(entryId)(model, message),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Match as M, Option, Schema as S } from 'effect'
|
|
2
|
-
import {
|
|
2
|
+
import { Update } from 'foldkit'
|
|
3
3
|
import { CalendarDate } from 'foldkit/calendar'
|
|
4
4
|
import {
|
|
5
5
|
Field,
|
|
@@ -84,32 +84,24 @@ export const init = (entryId: string, today: CalendarDate): Model => ({
|
|
|
84
84
|
|
|
85
85
|
// UPDATE
|
|
86
86
|
|
|
87
|
-
type UpdateReturn = readonly [
|
|
88
|
-
Model,
|
|
89
|
-
ReadonlyArray<Command.Command<Message>>,
|
|
90
|
-
Option.Option<OutMessage>,
|
|
91
|
-
]
|
|
92
|
-
|
|
93
87
|
const foldStartDateOutMessage = M.type<DatePicker.OutMessage>().pipe(
|
|
94
88
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
95
89
|
M.tagsExhaustive({
|
|
96
|
-
ChangedViewMonth: () => model =>
|
|
90
|
+
ChangedViewMonth: () => model => ({ model }),
|
|
97
91
|
SelectedDate:
|
|
98
92
|
({ date }) =>
|
|
99
|
-
model =>
|
|
100
|
-
evo(model, {
|
|
93
|
+
model => ({
|
|
94
|
+
model: evo(model, {
|
|
101
95
|
maybeStartDate: () => Option.some(date),
|
|
102
96
|
endDate: DatePicker.reflectMinDate(Option.some(date)),
|
|
103
97
|
}),
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
evo(model, {
|
|
98
|
+
}),
|
|
99
|
+
ClearedDate: () => model => ({
|
|
100
|
+
model: evo(model, {
|
|
108
101
|
maybeStartDate: () => Option.none(),
|
|
109
102
|
endDate: DatePicker.reflectMinDate(Option.none()),
|
|
110
103
|
}),
|
|
111
|
-
|
|
112
|
-
],
|
|
104
|
+
}),
|
|
113
105
|
}),
|
|
114
106
|
)
|
|
115
107
|
|
|
@@ -119,30 +111,27 @@ const foldStartDate = Update.foldChild({
|
|
|
119
111
|
write: (model, nextStartDate) =>
|
|
120
112
|
evo(model, { startDate: () => nextStartDate }),
|
|
121
113
|
toParentMessage: message => Message.GotStartDateMessage({ message }),
|
|
122
|
-
toParentOutMessage: () => Option.none(),
|
|
123
114
|
foldOutMessage: foldStartDateOutMessage,
|
|
124
115
|
})
|
|
125
116
|
|
|
126
117
|
const foldEndDateOutMessage = M.type<DatePicker.OutMessage>().pipe(
|
|
127
118
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
128
119
|
M.tagsExhaustive({
|
|
129
|
-
ChangedViewMonth: () => model =>
|
|
120
|
+
ChangedViewMonth: () => model => ({ model }),
|
|
130
121
|
SelectedDate:
|
|
131
122
|
({ date }) =>
|
|
132
|
-
model =>
|
|
133
|
-
evo(model, {
|
|
123
|
+
model => ({
|
|
124
|
+
model: evo(model, {
|
|
134
125
|
maybeEndDate: () => Option.some(date),
|
|
135
126
|
startDate: DatePicker.reflectMaxDate(Option.some(date)),
|
|
136
127
|
}),
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
evo(model, {
|
|
128
|
+
}),
|
|
129
|
+
ClearedDate: () => model => ({
|
|
130
|
+
model: evo(model, {
|
|
141
131
|
maybeEndDate: () => Option.none(),
|
|
142
132
|
startDate: DatePicker.reflectMaxDate(Option.none()),
|
|
143
133
|
}),
|
|
144
|
-
|
|
145
|
-
],
|
|
134
|
+
}),
|
|
146
135
|
}),
|
|
147
136
|
)
|
|
148
137
|
|
|
@@ -151,42 +140,36 @@ const foldEndDate = Update.foldChild({
|
|
|
151
140
|
read: (model: Model) => Option.some(model.endDate),
|
|
152
141
|
write: (model, nextEndDate) => evo(model, { endDate: () => nextEndDate }),
|
|
153
142
|
toParentMessage: message => Message.GotEndDateMessage({ message }),
|
|
154
|
-
toParentOutMessage: () => Option.none(),
|
|
155
143
|
foldOutMessage: foldEndDateOutMessage,
|
|
156
144
|
})
|
|
157
145
|
|
|
158
146
|
export const update = (model: Model, message: Message) =>
|
|
159
|
-
Message.match<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
Option.none(),
|
|
186
|
-
],
|
|
187
|
-
|
|
188
|
-
ClickedRemoveSelf: () => [model, [], Option.some(OutMessage.Removed())],
|
|
189
|
-
})
|
|
147
|
+
Message.match<Update.ReturnWithOutMessage<Model, Message, OutMessage>>(
|
|
148
|
+
message,
|
|
149
|
+
{
|
|
150
|
+
UpdatedCompany: ({ value }) => ({
|
|
151
|
+
model: evo(model, { company: () => validateCompany(value) }),
|
|
152
|
+
}),
|
|
153
|
+
|
|
154
|
+
UpdatedTitle: ({ value }) => ({
|
|
155
|
+
model: evo(model, { title: () => validateTitle(value) }),
|
|
156
|
+
}),
|
|
157
|
+
|
|
158
|
+
GotStartDateMessage: ({ message }) => foldStartDate(model, message),
|
|
159
|
+
|
|
160
|
+
GotEndDateMessage: ({ message }) => foldEndDate(model, message),
|
|
161
|
+
|
|
162
|
+
ToggledCurrentlyEmployed: ({ isChecked }) => ({
|
|
163
|
+
model: evo(model, { isCurrentlyEmployed: () => isChecked }),
|
|
164
|
+
}),
|
|
165
|
+
|
|
166
|
+
UpdatedDescription: ({ value }) => ({
|
|
167
|
+
model: evo(model, { description: () => value }),
|
|
168
|
+
}),
|
|
169
|
+
|
|
170
|
+
ClickedRemoveSelf: () => ({ model, outMessage: OutMessage.Removed() }),
|
|
171
|
+
},
|
|
172
|
+
)
|
|
190
173
|
|
|
191
174
|
// VALIDATION SUMMARY
|
|
192
175
|
|
|
@@ -54,20 +54,17 @@ export const GenerateEntryId = Command.define('GenerateEntryId', {
|
|
|
54
54
|
|
|
55
55
|
// UPDATE
|
|
56
56
|
|
|
57
|
-
type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>]
|
|
58
|
-
|
|
59
57
|
const foldEntryOutMessage: (
|
|
60
58
|
entryId: string,
|
|
61
59
|
) => (outMessage: Entry.OutMessage) => Update.Step<Model, Message> = entryId =>
|
|
62
60
|
M.type<Entry.OutMessage>().pipe(
|
|
63
61
|
M.withReturnType<Update.Step<Model, Message>>(),
|
|
64
62
|
M.tagsExhaustive({
|
|
65
|
-
Removed: () => model =>
|
|
66
|
-
evo(model, {
|
|
63
|
+
Removed: () => model => ({
|
|
64
|
+
model: evo(model, {
|
|
67
65
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
68
66
|
}),
|
|
69
|
-
|
|
70
|
-
],
|
|
67
|
+
}),
|
|
71
68
|
}),
|
|
72
69
|
)
|
|
73
70
|
|
|
@@ -85,24 +82,22 @@ const foldEntry = (entryId: string) =>
|
|
|
85
82
|
})
|
|
86
83
|
|
|
87
84
|
export const update = (model: Model, message: Message) =>
|
|
88
|
-
Message.match<
|
|
89
|
-
ClickedAddEntry: () =>
|
|
85
|
+
Message.match<Update.Return<Model, Message>>(message, {
|
|
86
|
+
ClickedAddEntry: () => ({ model, commands: [GenerateEntryId()] }),
|
|
90
87
|
|
|
91
|
-
SucceededGenerateEntryId: ({ entryId }) =>
|
|
92
|
-
evo(model, {
|
|
88
|
+
SucceededGenerateEntryId: ({ entryId }) => ({
|
|
89
|
+
model: evo(model, {
|
|
93
90
|
entries: Array.append(Entry.init(entryId, model.today)),
|
|
94
91
|
}),
|
|
95
|
-
|
|
96
|
-
],
|
|
92
|
+
}),
|
|
97
93
|
|
|
98
|
-
FailedGenerateEntryId: () =>
|
|
94
|
+
FailedGenerateEntryId: () => ({ model }),
|
|
99
95
|
|
|
100
|
-
RemovedEntry: ({ entryId }) =>
|
|
101
|
-
evo(model, {
|
|
96
|
+
RemovedEntry: ({ entryId }) => ({
|
|
97
|
+
model: evo(model, {
|
|
102
98
|
entries: Array.filter(entry => entry.id !== entryId),
|
|
103
99
|
}),
|
|
104
|
-
|
|
105
|
-
],
|
|
100
|
+
}),
|
|
106
101
|
|
|
107
102
|
GotEntryMessage: ({ entryId, message }) =>
|
|
108
103
|
foldEntry(entryId)(model, message),
|