Skip to content

Commit

Permalink
Merge pull request #79 from helsingborg-stad/feature/excel-import-err…
Browse files Browse the repository at this point in the history
…or-handling

Feature/excel-import-error-handling
  • Loading branch information
D3nnis38 authored Nov 29, 2024
2 parents 70ffe81 + efd7543 commit a8635a5
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 58 deletions.
1 change: 1 addition & 0 deletions src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const Menu = () => {
<Styled.Text onClick={() => navigate('/account/zones')}>Hantera zoner</Styled.Text>
<Styled.Text onClick={() => navigate('/account/zones/create')}>Lägg till zoner</Styled.Text>
<Styled.Text onClick={() => navigate('/account/events/import')}>Importera data</Styled.Text>
<Styled.Text onClick={() => navigate('/account/about')}>Om Sam</Styled.Text>
</Styled.SectionTwo>
<Styled.SectionThree>
<Styled.Text onClick={() => logOutAndRedirect()}>Logga ut</Styled.Text>
Expand Down
9 changes: 9 additions & 0 deletions src/components/SideBar/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ export const SideBar = () => {
>
Importera data
</Button>
<Button
onClick={handleNavigate('/account/about')}
buttonSize={ButtonSize.SMALL}
secondary={activePath === '/account/about'}
tertiary={activePath !== '/account/about'}
type="button"
>
Om Sam
</Button>
</Styled.SideBarContainer>
);
};
61 changes: 61 additions & 0 deletions src/modules/Account/About/About.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { SideBar } from 'components/SideBar';
import { Link } from 'components/Link';
import * as Styled from './styled';

export const About = () => (
<Styled.ContentContainer>
<SideBar />
<Styled.InfoContainer>
<Styled.Header>Om Sam</Styled.Header>
<p>
Sam samlar in transportdata för att kunna dela datan mellan olika aktörer i transportkedjan.
Genom tillgänglig data kan beställaren fà bättre förstäelse för hur transporterna
inom olika omräden går och kan använda datan för att bli smartare beställare.
Leverantörer och transportörer kan använda datan för att hitta samarbeten och samlastning.
Mälet med Sam är smartare logistik kring transporter och minskade
körningar för klimatets skull.
</p>
<h2 style={{ marginBottom: '10px', marginTop: '60px' }}>Så här fungerar Sam</h2>
<p>
Tjänsten Sam bestär av en mobilapp som används av förare,
och den här webbsidan där alla sparade leveranser samlas.
Just nu är tjänsten sà pass utvecklad att vi kan beskriva
transporter som gär till och fràn olika verksamheter i staden,
via geofencing*. Det betyder att endast leveranser till geofencade adresser
registreras - andra stopp pá vägen kommer inte registreras pá webbsidan
</p>
<br />
<p>
<i>
*Geofence är en internationell fackterm. Den kan översättas med &quot;geostaket&quot;
och är ett geografiskt avgränsat eller definierat omräde som bestämts och som
&quot;inhägnats&quot; med en programvara.
</i>
</p>
<h2 style={{ marginBottom: '10px', marginTop: '60px' }}>Leverera transportdata till Sam</h2>
<p style={{ marginBottom: '8px' }}>
Det finns två sätt att leverera data till Sam.
</p>
<ol>
<li>
Använd appen Sam
<br />
Föraren laddar ner appen till sin telefon. Föraren startar spärningen
i appen vid start av en körning.
Varje gäng transporten befinner sig inom ett geofencat omräde blir
det en datapunkt som sparas och blir synlig pà webbsidan.
</li>
<li>
Leverera en rapport
<br />
Istället för att använda appen Sam kan leverantör eller transportör hämta
motsvarande data frản sitt logistiksystem/TMS (Transport Management System)
och skicka rapport till kontaktperson enligt
överenskommet intervall.
{' '}
<Link href="/Template.xlsx" download="mall.xlsx" label="[Mall för rapport]" />
</li>
</ol>
</Styled.InfoContainer>
</Styled.ContentContainer>
);
3 changes: 3 additions & 0 deletions src/modules/Account/About/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { About } from './About';

export default About;
22 changes: 22 additions & 0 deletions src/modules/Account/About/styled.ts
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 InfoContainer = 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-lg);
font-weight: var(--font-weight-800);
line-height: var(--line-height-xxxl);
margin-bottom: var(--spacing-md);
font-family: var(--font-family);
`;
2 changes: 2 additions & 0 deletions src/modules/Account/AccountRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const ZonesSettings = lazy(() => import('./ZonesSettings'));
const CreateZones = lazy(() => import('./CreateZones'));
const EditZone = lazy(() => import('./EditZone'));
const ImportEvents = lazy(() => import('./ImportEvents'));
const About = lazy(() => import('./About'));

export const AccountRouter = () => (
<DeliveryLayout>
Expand All @@ -15,6 +16,7 @@ export const AccountRouter = () => (
<Route path="/zones/:id/edit" element={<EditZone />} />
<Route path="/zones" element={<ZonesSettings />} />
<Route path="/events/import" element={<ImportEvents />} />
<Route path="/about" element={<About />} />
<Route path="/" element={<AccountSettings />} />
</Routes>
</DeliveryLayout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import {
Input, Button,
Link,
} from 'components';
import {
Check, Download, Error, InsertDriveFileOutlined,
} from '@mui/icons-material';
import * as Styled from './styled';
import { useImportEventsForm } from './hooks';

Expand All @@ -18,8 +21,13 @@ export const ImportEventsForm = () => {
apiErrorText,
isLoading,
importFile,
importErrorText,
setImportFile,
uploadStatus,
} = useImportEventsForm();

const errors = importErrorText ? importErrorText.split('|') : [];

const {
getRootProps,
getInputProps,
Expand Down Expand Up @@ -47,26 +55,68 @@ export const ImportEventsForm = () => {
: <p>Dra zoner eller klicka för att ladda upp</p>
}
</Styled.DropArea>
<Link href="/Template.xlsx" download="mall.xlsx" label="Ladda ner mall" />
<Styled.ButtonContainer>
<Button onClick={submitFileForm} type="button" disabled={isLoading || !importFile}>Importera</Button>
</Styled.ButtonContainer>
{importFile && (
<Styled.FileContainer>
<Styled.File>
<InsertDriveFileOutlined />
<p><b>{importFile?.name}</b></p>
</Styled.File>
<Styled.FileActions>
{uploadStatus === 'success' && <Check color="success" />}
{uploadStatus === 'error' && <Error color="error" />}
{uploadStatus === 'idle' && <Styled.TextButton onClick={() => setImportFile(null)}>Ta bort</Styled.TextButton>}
</Styled.FileActions>
</Styled.FileContainer>
)}
{errors && errors.length > 0 && (
<>
<Styled.ErrorText>
<b>
{errors.length}
{' '}
fel
</b>
</Styled.ErrorText>
{errors.map((error) => (
<Styled.ErrorText style={{ margin: 0 }}>{error}</Styled.ErrorText>
))}
</>
)}
{importFile && (
<Styled.ButtonContainer>
<Button onClick={submitFileForm} type="button" disabled={!importFile}>Importera</Button>
</Styled.ButtonContainer>
)}
</form>
) : (
<form>
<Input
label="Lösenord"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Lösenord"
/>
<form onSubmit={submitPasswordForm}>
<Styled.Paragraph>
Transportdata kan delas i Sam genom import av rapporter. Rapporten skickar du
enligt överenskommet intervall till din kontaktperson.
Kontaktpersonen importerar in rapporten och datan blir sen synlig i Sam.
</Styled.Paragraph>
<Styled.DownloadContainer>
<Download />
<Link href="/Template.xlsx" download="mall.xlsx" label="Ladda ner rapportmall" />
</Styled.DownloadContainer>
{' '}
<h3 style={{ marginBottom: '8px' }}>För kontaktperson</h3>
<Styled.InputContainer>
<Input
label="Ange lösenord för att ladda upp rapporter"
type="password"
value={password}
name="password"
onChange={(e) => setPassword(e.target.value)}
placeholder="Lösenord"
/>
</Styled.InputContainer>
{apiErrorText && <Styled.ErrorText>{apiErrorText}</Styled.ErrorText>}
<Styled.ButtonContainer>
<Button onClick={submitPasswordForm} type="button" disabled={isLoading}>Verifiera</Button>
</Styled.ButtonContainer>
</form>
)}
{apiErrorText && <Styled.ErrorText>{apiErrorText}</Styled.ErrorText>}
</Styled.ContentContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@
import { AxiosError } from 'axios';
import { useState, useCallback } from 'react';
import { useEventApi } from 'hooks/useEventApi';
import { useNavigate } from 'react-router-dom';

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 [importErrorText, setImportErrorText] = useState<string>('');
const [passwordIsCorrect, setPasswordIsCorrect] = useState<boolean>(false);
const navigate = useNavigate();
const [uploadStatus, setUploadStatus] = useState<'idle' | 'success' | 'error'>('idle');

const { importEventsPassword, importEventsByExcel } = useEventApi();

const onDrop = useCallback((acceptedFiles: any) => {
const file = acceptedFiles[0];
setUploadStatus('idle');
setImportErrorText('');
setImportFile(file);
}, []);

Expand All @@ -24,10 +26,12 @@ export const useImportEventsForm = () => {
try {
await importEventsByExcel(importFile as File, password);
setApiErrorText('');
navigate('/events/grouped');
setImportErrorText('');
setUploadStatus('success');
} catch (error: AxiosError | any) {
if (error) {
setApiErrorText(error.response.data.message);
setUploadStatus('error');
setImportErrorText(error.response.data.message);
}
}
setIsLoading(false);
Expand Down Expand Up @@ -63,5 +67,8 @@ export const useImportEventsForm = () => {
passwordIsCorrect,
password,
importFile,
importErrorText,
setImportFile,
uploadStatus,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ export const InputContainer = styled.div`
`;

export const ButtonContainer = styled.div`
display: flex;
justify-content: flex-end;
width: 55%;
margin-top: var(--spacing-xs);
gap: var(--spacing-xs);
`;
Expand Down Expand Up @@ -102,3 +101,49 @@ export const ListItem = styled.li`
border-bottom: none;
}
`;

export const Paragraph = styled.p`
line-height: var(--line-height-md);
`;

export const DownloadContainer = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-xxs);
margin-top: var(--spacing-xs);
margin-bottom: var(--spacing-xl);
a {
color: var(--color-black);
text-decoration: none;
font-weight: bold;
font-size: var(--font-size-body-md);
}
`;

export const File = styled.div`
display: flex;
align-items: center;
gap: var(--spacing-xxs);
margin-top: var(--spacing-xs);
`;

export const FileContainer = styled.div`
display: flex;
justify-content: space-between;
`;
export const TextButton = styled.button`
background: none;
border: none;
color: var(--color-primary);
text-decoration: underline;
cursor: pointer;
font-size: var(--font-size-body-md);
&:hover {
text-decoration: none;
}
`;

export const FileActions = styled.div`
display: flex;
align-items: end;
`;
4 changes: 2 additions & 2 deletions src/modules/Account/ImportEvents/styled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ export const FormContainer = styled.div`
`;

export const Header = styled.h1`
font-size: var(--font-size-heading-xs);
font-size: var(--font-size-heading-lg);
font-weight: var(--font-weight-800);
line-height: var(--line-height-xxxl);
margin-bottom: var(--spacing-xxs);
margin-bottom: var(--spacing-md);
font-family: var(--font-family);
`;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Input, Checkbox, Button } from 'components';
import { Input, Button } from 'components';
import * as Styled from './styled';
import { useCreateAccountForm } from '../../hooks';

export const CreateAccountForm = () => {
const {
setFieldValue, formFields, errors, setConsentValue, submitForm, isLoading,
setFieldValue, formFields, errors, submitForm, isLoading,
} = useCreateAccountForm();

return (
Expand Down Expand Up @@ -82,21 +82,6 @@ export const CreateAccountForm = () => {
error={errors.pinCode}
info="För att logga in i appen används en pinkod. Bestäm vilken pinkod din verksamhet ska använda. Koden ska bestå av 6 siffror med minst 3 unika siffror och där högst 2 siffror i följd är lika."
/>
<Styled.ChecboxContainer>

<Checkbox
id="Consent"
checked={formFields.consent}
onChange={setConsentValue}
error={errors.consent}
>
<Styled.Label>
Genom att skapa konto säger du ja till
{' '}
<Styled.Link target="_blank" href="https://helsingborg.se/">xxx</Styled.Link>
</Styled.Label>
</Checkbox>
</Styled.ChecboxContainer>
<Styled.ButtonContainer>
<Button type="submit" disabled={isLoading} onClick={() => submitForm}>Skapa konto</Button>
</Styled.ButtonContainer>
Expand Down
Loading

0 comments on commit a8635a5

Please sign in to comment.