-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add import events through excel
- Loading branch information
Showing
18 changed files
with
334 additions
and
4 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
Binary file not shown.
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
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 |
---|---|---|
@@ -1,13 +1,19 @@ | ||
import { getEvents, exportEvents, getGroupedEvents } from 'api/event'; | ||
import { | ||
getEvents, exportEvents, getGroupedEvents, importEvents, postImportEventsPassword, | ||
} from 'api/event'; | ||
|
||
export const useEventApi = () => { | ||
const getAllEvents = (filter?: string) => getEvents(filter); | ||
const exportAllEvents = (filter?: string) => exportEvents(filter); | ||
const getAllGroupedEvents = (filter?: string) => getGroupedEvents(filter); | ||
const importEventsPassword = (password: string) => postImportEventsPassword(password); | ||
const importEventsByExcel = (file: File, password: string) => importEvents(file, password); | ||
|
||
return { | ||
getAllEvents, | ||
exportAllEvents, | ||
getAllGroupedEvents, | ||
importEventsPassword, | ||
importEventsByExcel, | ||
}; | ||
}; |
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,30 @@ | ||
import { useEffect } from 'react'; | ||
import { useAuth } from 'hooks/useAuth'; | ||
import { SideBar } from 'components'; | ||
import { ImportEventsForm } from './components'; | ||
import * as Styled from './styled'; | ||
|
||
export const ImportEvents = () => { | ||
const { hasToken } = useAuth(); | ||
const isAuthenticated = hasToken(); | ||
|
||
useEffect(() => { | ||
if (!isAuthenticated) { | ||
window.location.href = '/auth/login'; | ||
} | ||
}, [isAuthenticated]); | ||
|
||
if (!isAuthenticated) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Styled.ContentContainer> | ||
<SideBar /> | ||
<Styled.FormContainer> | ||
<Styled.Header>Importera data</Styled.Header> | ||
<ImportEventsForm /> | ||
</Styled.FormContainer> | ||
</Styled.ContentContainer> | ||
); | ||
}; |
71 changes: 71 additions & 0 deletions
71
src/modules/Account/ImportEvents/components/ImportEventsForm/ImportEventsForm.tsx
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,71 @@ | ||
/* eslint-disable react/jsx-props-no-spreading */ | ||
import { useDropzone } from 'react-dropzone'; | ||
import { | ||
Input, Button, | ||
Link, | ||
} from 'components'; | ||
import * as Styled from './styled'; | ||
import { useImportEventsForm } from './hooks'; | ||
|
||
export const ImportEventsForm = () => { | ||
const { | ||
onDrop, | ||
passwordIsCorrect, | ||
setPassword, | ||
password, | ||
submitFileForm, | ||
submitPasswordForm, | ||
apiErrorText, | ||
isLoading, | ||
} = useImportEventsForm(); | ||
|
||
const { | ||
getRootProps, | ||
getInputProps, | ||
isFocused, | ||
isDragAccept, | ||
isDragReject, | ||
isDragActive, | ||
} = useDropzone({ | ||
onDrop, | ||
accept: { | ||
'application/json': ['.xlsx'], | ||
}, | ||
maxFiles: 1, | ||
}); | ||
|
||
return ( | ||
<Styled.ContentContainer> | ||
{passwordIsCorrect ? ( | ||
<form onSubmit={submitFileForm}> | ||
<Styled.DropArea {...getRootProps({ isFocused, isDragAccept, isDragReject })}> | ||
<input {...getInputProps()} /> | ||
{ | ||
isDragActive | ||
? <p>Ladda upp zoner...</p> | ||
: <p>Dra zoner eller klicka för att ladda upp</p> | ||
} | ||
</Styled.DropArea> | ||
<Link href="/src/assets/Template.xlsx" download="mall.xlsx" label="Ladda ner mall" /> | ||
<Styled.ButtonContainer> | ||
<Button onClick={submitFileForm} type="button" disabled={isLoading}>Importera</Button> | ||
</Styled.ButtonContainer> | ||
</form> | ||
) : ( | ||
<form> | ||
<Input | ||
label="Lösenord" | ||
type="password" | ||
value={password} | ||
onChange={(e) => setPassword(e.target.value)} | ||
placeholder="Lösenord" | ||
/> | ||
<Styled.ButtonContainer> | ||
<Button onClick={submitPasswordForm} type="button" disabled={isLoading}>Verifiera</Button> | ||
</Styled.ButtonContainer> | ||
</form> | ||
)} | ||
{apiErrorText && <Styled.ErrorText>{apiErrorText}</Styled.ErrorText>} | ||
</Styled.ContentContainer> | ||
); | ||
}; |
1 change: 1 addition & 0 deletions
1
src/modules/Account/ImportEvents/components/ImportEventsForm/hooks/index.ts
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 @@ | ||
export * from './useImportEventsForm'; |
1 change: 1 addition & 0 deletions
1
...dules/Account/ImportEvents/components/ImportEventsForm/hooks/useImportEventsForm/index.ts
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 @@ | ||
export * from './useImportEventsForm'; |
63 changes: 63 additions & 0 deletions
63
...ImportEvents/components/ImportEventsForm/hooks/useImportEventsForm/useImportEventsForm.ts
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,63 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
import { AxiosError } from 'axios'; | ||
import { useState, useCallback } from 'react'; | ||
import { useEventApi } from 'hooks/useEventApi'; | ||
|
||
export const useImportEventsForm = () => { | ||
const [isLoading, setIsLoading] = useState(false); | ||
const [importFile, setImportFile] = useState<File | null>(null); | ||
const [password, setPassword] = useState<string>(''); | ||
const [apiErrorText, setApiErrorText] = useState<string>(''); | ||
const [passwordIsCorrect, setPasswordIsCorrect] = useState<boolean>(false); | ||
|
||
const { importEventsPassword, importEventsByExcel } = useEventApi(); | ||
|
||
const onDrop = useCallback((acceptedFiles: any) => { | ||
const file = acceptedFiles[0]; | ||
setImportFile(file); | ||
}, []); | ||
|
||
const submitFileForm = async () => { | ||
setIsLoading(true); | ||
try { | ||
await importEventsByExcel(importFile as File, password); | ||
setApiErrorText(''); | ||
} catch (error: AxiosError | any) { | ||
if (error) { | ||
setApiErrorText(error.response.statusText); | ||
} | ||
} | ||
setIsLoading(false); | ||
}; | ||
|
||
const submitPasswordForm = async () => { | ||
setIsLoading(true); | ||
try { | ||
await importEventsPassword(password); | ||
setPasswordIsCorrect(true); | ||
setApiErrorText(''); | ||
} catch (error: AxiosError | any) { | ||
if (error) { | ||
if (error.response.status === 401) { | ||
setApiErrorText( | ||
'Felaktigt lösenord', | ||
); | ||
} else { | ||
setApiErrorText(error.response.statusText); | ||
} | ||
} | ||
} | ||
setIsLoading(false); | ||
}; | ||
|
||
return { | ||
isLoading, | ||
onDrop, | ||
submitFileForm, | ||
submitPasswordForm, | ||
apiErrorText, | ||
setPassword, | ||
passwordIsCorrect, | ||
password, | ||
}; | ||
}; |
1 change: 1 addition & 0 deletions
1
src/modules/Account/ImportEvents/components/ImportEventsForm/index.ts
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 @@ | ||
export * from './ImportEventsForm'; |
104 changes: 104 additions & 0 deletions
104
src/modules/Account/ImportEvents/components/ImportEventsForm/styled.ts
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,104 @@ | ||
import styled from 'styled-components'; | ||
|
||
const getColor = (props: any) => { | ||
if (props.isDragAccept) { | ||
return '#00e676'; | ||
} | ||
if (props.isDragReject) { | ||
return '#ff1744'; | ||
} | ||
if (props.isFocused) { | ||
return '#2196f3'; | ||
} | ||
return '#eeeeee'; | ||
}; | ||
|
||
export const ContentContainer = styled.div` | ||
margin-top: var(--spacing-xxs); | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--spacing-xs); | ||
width: 100%; | ||
gap: var(--spacing-xs); | ||
`; | ||
|
||
export const DropArea = styled.div` | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 20px; | ||
border-width: 2px; | ||
border-radius: 2px; | ||
border-color: ${(props) => getColor(props)}; | ||
border-style: dashed; | ||
background-color: #fafafa; | ||
color: #bdbdbd; | ||
outline: none; | ||
transition: border .24s ease-in-out; | ||
`; | ||
|
||
export const SplitContainer = styled.div` | ||
display: flex; | ||
flex-direction: row; | ||
gap: var(--spacing-xs); | ||
width: 100%; | ||
margin-bottom: var(--spacing-xxs); | ||
border-bottom: 1px solid var(--color-gray-12); | ||
padding-bottom: var(--spacing-xs); | ||
`; | ||
|
||
export const MapContainer = styled.div` | ||
width: 45%; | ||
height: 375px; | ||
`; | ||
|
||
export const InputContainer = styled.div` | ||
width: 55%; | ||
display: flex; | ||
flex-direction: column; | ||
gap: var(--spacing-xxxs); | ||
`; | ||
|
||
export const ButtonContainer = styled.div` | ||
display: flex; | ||
justify-content: flex-end; | ||
margin-top: var(--spacing-xs); | ||
gap: var(--spacing-xs); | ||
`; | ||
|
||
export const ErrorText = styled.p` | ||
font-size: var(--font-size-body-xs); | ||
color: var(--color-red-1); | ||
line-height: var(--line-height-xxs); | ||
font-weight: var(--font-weight-500); | ||
margin-top: 10px; | ||
`; | ||
|
||
export const List = styled.ul` | ||
list-style: none; | ||
margin-bottom: var(--spacing-xxs); | ||
width: 321px; | ||
@media (max-width: 768px) { | ||
width: 238px; | ||
} | ||
position: absolute; | ||
background-color: var(--color-white); | ||
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); | ||
padding: var(--spacing-xxs); | ||
padding-bottom: 0; | ||
border-radius: var(--border-radius-sm); | ||
`; | ||
|
||
export const ListItem = styled.li` | ||
border-bottom: 1px solid var(--color-gray-12); | ||
cursor: pointer; | ||
margin-bottom: var(--spacing-xxs); | ||
&:hover { | ||
color: var(--color-gray-2); | ||
transition: color 0.2s ease-in-out; | ||
} | ||
&:last-child { | ||
border-bottom: none; | ||
} | ||
`; |
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 @@ | ||
export * from './ImportEventsForm'; |
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,3 @@ | ||
import { ImportEvents } from './ImportEvents'; | ||
|
||
export default ImportEvents; |
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,22 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const ContentContainer = styled.div` | ||
padding: 36px 32px; | ||
padding-bottom: 64px; | ||
`; | ||
|
||
export const FormContainer = styled.div` | ||
width: 600px; | ||
margin: 24px auto 32px; | ||
@media (max-width: 768px) { | ||
width: 450px; | ||
} | ||
`; | ||
|
||
export const Header = styled.h1` | ||
font-size: var(--font-size-heading-xs); | ||
font-weight: var(--font-weight-800); | ||
line-height: var(--line-height-xxxl); | ||
margin-bottom: var(--spacing-xxs); | ||
font-family: var(--font-family); | ||
`; |
Oops, something went wrong.