-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add redux actions and form for creating lendable objects
- Loading branch information
Showing
13 changed files
with
410 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import callAPI from 'app/actions/callAPI'; | ||
import { lendableObjectSchema } from 'app/reducers'; | ||
import type { Thunk } from 'app/types'; | ||
import { LendableObject } from './ActionTypes'; | ||
|
||
export function fetchAllLendableObjects(): Thunk<any> { | ||
return callAPI({ | ||
types: LendableObject.FETCH, | ||
endpoint: '/lendableobject/', | ||
schema: [lendableObjectSchema], | ||
meta: { | ||
errorMessage: 'Henting av utlånsobjekter failet', | ||
}, | ||
propagateError: true, | ||
}); | ||
} | ||
|
||
export function fetchLendableObject(id: number): Thunk<any> { | ||
return callAPI({ | ||
types: LendableObject.FETCH, | ||
endpoint: `/lendableobject/${id}/`, | ||
schema: lendableObjectSchema, | ||
meta: { | ||
errorMessage: 'Henting av utlånsobjekt feilet', | ||
}, | ||
propagateError: true, | ||
}); | ||
} | ||
|
||
export function deleteLendableObject(id: number): Thunk<any> { | ||
return callAPI({ | ||
types: LendableObject.DELETE, | ||
endpoint: `/lendableobject/${id}/`, | ||
method: 'DELETE', | ||
meta: { | ||
id, | ||
errorMessage: 'Sletting av utlånsobjekt feilet', | ||
}, | ||
}); | ||
} | ||
|
||
export function createLendableObject(data: any): Thunk<any> { | ||
return callAPI({ | ||
types: LendableObject.CREATE, | ||
endpoint: '/lendableobject/', | ||
method: 'POST', | ||
body: data, | ||
schema: lendableObjectSchema, | ||
meta: { | ||
errorMessage: 'Opprettelse av utlånsobjekt feilet', | ||
}, | ||
}); | ||
} | ||
|
||
export function editLendableObject({ | ||
id, | ||
...data | ||
}: Record<string, any>): Thunk<any> { | ||
return callAPI({ | ||
types: LendableObject.EDIT, | ||
endpoint: `/lendableobject/${id}/`, | ||
method: 'PUT', | ||
body: data, | ||
meta: { | ||
errorMessage: 'Endring av utlånsobjekt feilet', | ||
}, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { createSelector } from '@reduxjs/toolkit'; | ||
import { LendableObject } from 'app/actions/ActionTypes'; | ||
import type { RootState } from 'app/store/createRootReducer'; | ||
import createEntityReducer from 'app/utils/createEntityReducer'; | ||
import type { EntityId } from '@reduxjs/toolkit'; | ||
|
||
export default createEntityReducer({ | ||
key: 'lendableObjects', | ||
types: { | ||
fetch: LendableObject.FETCH, | ||
mutate: LendableObject.CREATE, | ||
delete: LendableObject.DELETE, | ||
}, | ||
}); | ||
export const selectLendableObjects = createSelector( | ||
(state: RootState) => state.lendableObjects.byId, | ||
(state: RootState) => state.lendableObjects.items, | ||
(lendableObjectsById, lendableObjectIds) => | ||
lendableObjectIds.map((id) => lendableObjectsById[id]) | ||
); | ||
export const selectLendableObjectById = createSelector( | ||
(state: RootState) => state.lendableObjects.byId, | ||
(_: RootState, id: EntityId) => id, | ||
(lendableObjectsById, lendableObjectId) => | ||
lendableObjectsById[lendableObjectId] | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import dayGridPlugin from '@fullcalendar/daygrid'; | ||
import interactionPlugin from '@fullcalendar/interaction'; | ||
import FullCalendar from '@fullcalendar/react'; | ||
import timeGridPlugin from '@fullcalendar/timegrid'; | ||
import moment from 'moment-timezone'; | ||
import { Helmet } from 'react-helmet-async'; | ||
import { useParams, Link } from 'react-router-dom'; | ||
import { Content } from 'app/components/Content'; | ||
import NavigationTab from 'app/components/NavigationTab'; | ||
import type { DetailedLendableObject } from 'app/store/models/LendableObject'; | ||
|
||
type Params = { | ||
lendableObjectId: string; | ||
}; | ||
|
||
const LendableObjectAdminDetail = () => { | ||
const { lendableObjectId } = useParams<Params>(); | ||
|
||
const lendingRequest = { | ||
id: 1, | ||
user: { | ||
id: 1, | ||
username: 'Eik', | ||
fullName: 'Test Testesen', | ||
}, | ||
message: 'Jeg vil gjerne låne Soundboks til hyttetur:)', | ||
startTime: moment().subtract({ hours: 2 }), | ||
endTime: moment(), | ||
approved: false, | ||
}; | ||
|
||
const lendableObject: DetailedLendableObject = { | ||
id: lendableObjectId, | ||
title: 'Soundbox', | ||
description: 'En soundbox som kan brukes til å spille av lyder', | ||
lendingCommentPrompt: 'Hvorfor ønsker du å låne soundboks', | ||
image: | ||
'https://www.tntpyro.no/wp-content/uploads/2021/08/141_1283224098.jpg', | ||
}; | ||
|
||
const otherLoans = [ | ||
{ | ||
id: 2, | ||
startTime: moment().subtract({ days: 1, hours: 2 }), | ||
endTime: moment().subtract({ hours: 8 }), | ||
}, | ||
{ | ||
id: 3, | ||
startTime: moment().subtract({ hours: 6 }), | ||
endTime: moment().subtract({ hours: 2 }), | ||
}, | ||
]; | ||
|
||
const requestEvent = { | ||
id: String(lendingRequest.id), | ||
title: lendingRequest.user.fullName, | ||
start: lendingRequest.startTime.toISOString(), | ||
end: lendingRequest.endTime.toISOString(), | ||
backgroundColor: '#e11617', | ||
borderColor: '#e11617', | ||
}; | ||
|
||
const otherLoanEvents = otherLoans.map((loan) => ({ | ||
id: String(loan.id), | ||
title: 'Test', | ||
start: loan.startTime.toISOString(), | ||
end: loan.endTime.toISOString(), | ||
backgroundColor: '#999999', | ||
borderColor: '#999999', | ||
})); | ||
|
||
const otherLoanRequests = [ | ||
{ | ||
id: 5, | ||
startTime: moment().subtract({ hours: 2 }), | ||
endTime: moment().add({ hours: 2 }), | ||
}, | ||
]; | ||
|
||
const otherLoanRequestEvents = otherLoanRequests.map((loan) => ({ | ||
id: String(loan.id), | ||
title: 'Test', | ||
start: loan.startTime.toISOString(), | ||
end: loan.endTime.toISOString(), | ||
backgroundColor: '#f57676', | ||
borderColor: '#f57676', | ||
})); | ||
|
||
return ( | ||
<Content banner={lendableObject.image}> | ||
<Helmet title={`Godkjenn utlån av ${lendableObject.title}`} /> | ||
<NavigationTab | ||
title={`Godkjenn utlån av ${lendableObject.title}`} | ||
></NavigationTab> | ||
<p> | ||
{lendingRequest.message} -{' '} | ||
<Link to={`/users/${lendingRequest.user.username}`}> | ||
{lendingRequest.user.fullName} | ||
</Link>{' '} | ||
</p> | ||
<FullCalendar | ||
plugins={[interactionPlugin, timeGridPlugin, dayGridPlugin]} | ||
initialView="timeGridWeek" | ||
slotDuration={'01:00:00'} | ||
nowIndicator | ||
expandRows | ||
slotLabelInterval={'02:00:00'} | ||
slotLabelFormat={{ | ||
timeStyle: 'short', | ||
}} | ||
allDaySlot={false} | ||
locale="nb" | ||
firstDay={1} | ||
headerToolbar={{ | ||
left: 'prev,today,next', | ||
center: 'title', | ||
right: 'timeGridWeek,dayGridMonth', | ||
}} | ||
events={[requestEvent, ...otherLoanEvents, ...otherLoanRequestEvents]} | ||
/> | ||
</Content> | ||
); | ||
}; | ||
|
||
export default LendableObjectAdminDetail; |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { Field, FormSpy } from 'react-final-form'; | ||
import { useParams } from 'react-router-dom'; | ||
import { createLendableObject } from 'app/actions/LendingObjectActions'; | ||
import { Content } from 'app/components/Content'; | ||
import { | ||
Button, | ||
EditorField, | ||
Form, | ||
SelectInput, | ||
TextInput, | ||
} from 'app/components/Form'; | ||
import LegoFinalForm from 'app/components/Form/LegoFinalForm'; | ||
import SubmissionError from 'app/components/Form/SubmissionError'; | ||
import { useAppDispatch } from 'app/store/hooks'; | ||
import { roleOptions } from 'app/utils/constants'; | ||
import { spySubmittable } from 'app/utils/formSpyUtils'; | ||
|
||
type Params = { | ||
lendableObjectId: string | undefined; | ||
}; | ||
|
||
const LendableObjectEdit = () => { | ||
const { lendableObjectId } = useParams<Params>(); | ||
const isNew = lendableObjectId === undefined; | ||
|
||
const dispatch = useAppDispatch(); | ||
|
||
const onSubmit = (values) => | ||
dispatch( | ||
createLendableObject({ | ||
...values, | ||
responsibleGroups: values.responsibleGroups.map((group) => group.id), | ||
responsibleRoles: values.responsibleRoles.map((role) => role.value), | ||
}) | ||
); | ||
|
||
return ( | ||
<Content> | ||
<LegoFinalForm onSubmit={onSubmit} subscription={{}}> | ||
{({ handleSubmit }) => ( | ||
<Form onSubmit={handleSubmit}> | ||
<FormSpy> | ||
{(form) => { | ||
return <pre>{JSON.stringify(form.values, undefined, 2)}</pre>; | ||
}} | ||
</FormSpy> | ||
<Field | ||
name="title" | ||
label="Navn" | ||
placeholder="Navn på utleieobjekt" | ||
component={TextInput.Field} | ||
/> | ||
<Field | ||
name="description" | ||
label="Beskrivelse" | ||
component={EditorField.Field} | ||
initialized={true} | ||
/> | ||
<Field | ||
name="responsibleGroups" | ||
filter={['users.abakusgroup']} | ||
label="Ansvarlige grupper" | ||
placeholder="Skriv inn gruppene som skal kunne administrere objektet" | ||
component={SelectInput.AutocompleteField} | ||
isMulti | ||
/> | ||
<Field | ||
label="Ansvarlige roller (hvis du lar denne stå tom inkluderer du alle i gruppen!)" | ||
name="responsibleRoles" | ||
isMulti | ||
placeholder="Velg rolle" | ||
options={roleOptions} | ||
component={SelectInput.Field} | ||
/> | ||
<Field | ||
name="location" | ||
label="Posisjon" | ||
placeholder="Hvor befinner objektet seg?" | ||
component={TextInput.Field} | ||
/> | ||
<SubmissionError /> | ||
{spySubmittable((submittable) => ( | ||
<Button disabled={!submittable} submit> | ||
{isNew ? 'Opprett utlåndsobjekt' : 'Lagre endringer'} | ||
</Button> | ||
))} | ||
</Form> | ||
)} | ||
</LegoFinalForm> | ||
</Content> | ||
); | ||
}; | ||
|
||
export default LendableObjectEdit; |
Oops, something went wrong.