Skip to content

Commit 47ecc4c

Browse files
committed
chore: merge
2 parents 42f443d + 3c2ecbe commit 47ecc4c

File tree

19 files changed

+417
-170
lines changed

19 files changed

+417
-170
lines changed

src/App.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1+
import { Fragment } from 'react';
12
import { BrowserRouter } from 'react-router-dom';
23

34
import { Routes } from './routes/Routes';
45
import { SessionProvider } from './contexts';
6+
import { Toaster } from './components/ui/toaster';
57

68
const App = () => {
79
return (
8-
<BrowserRouter>
9-
<SessionProvider>
10-
<Routes />
11-
</SessionProvider>
12-
</BrowserRouter>
10+
<Fragment>
11+
<Toaster />
12+
<BrowserRouter>
13+
<SessionProvider>
14+
<Routes />
15+
</SessionProvider>
16+
</BrowserRouter>
17+
</Fragment>
1318
);
1419
};
1520

src/api/api.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,26 @@
1-
import axios from 'axios';
2-
3-
console.log(import.meta.env.VITE_API_URL);
1+
import axios, { AxiosRequestHeaders } from 'axios';
42

53
const api = axios.create({
64
baseURL: import.meta.env.VITE_API_URL ?? 'https://api.sos-rs.com',
75
});
86

7+
api.interceptors.request.use((config) => {
8+
if (!config.headers) config.headers = {} as AxiosRequestHeaders;
9+
const token = localStorage.getItem('token');
10+
if (token) config.headers.Authorization = `Bearer ${token}`;
11+
return config;
12+
});
13+
14+
api.interceptors.response.use(
15+
(config) => {
16+
return config;
17+
},
18+
(error) => {
19+
if (error.response && error.response.status === 401) {
20+
localStorage.removeItem('token');
21+
}
22+
return Promise.reject(error);
23+
}
24+
);
25+
926
export { api };

src/components/ShelterListItem/ShelterListItem.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const ShelterListItem = (props: IShelterListItemProps) => {
5454
<div className="flex flex-col gap-3">
5555
<Separator className="mt-2" />
5656
<p className="text-muted-foreground text-sm md:text-lg font-medium">
57-
Necessita urgente de doações de:
57+
Precisa urgente de doações de:
5858
</p>
5959
<div className="flex gap-2 flex-wrap">
6060
{tags.map((s, idx) => (

src/contexts/SessionContext/types.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,4 @@
1-
export interface ISession {
2-
id: string;
3-
userId: string;
4-
ip: string;
5-
userAgent: string;
6-
active: string;
7-
createdAt: string;
8-
updatedAt: string;
9-
}
10-
11-
export enum LoginType {
12-
User = "user",
13-
}
1+
import { ISession } from '@/service/sessions/types';
142

153
export interface ISessionContext {
164
session: ISession | null;

src/lib/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ const colorStatusPriority = (priority: SupplyPriority) => {
3030
* deprecated
3131
*/
3232
function nameStatusPriority(priority: SupplyPriority) {
33-
if (priority === SupplyPriority.Needing) return 'Necessita urgentimente';
34-
if (priority === SupplyPriority.Urgent) return 'Urgente';
33+
if (priority === SupplyPriority.Needing) return 'Precisa urgentimente';
34+
if (priority === SupplyPriority.Urgent) return 'Precisa';
3535
if (priority === SupplyPriority.UnderControl) return 'Sob-controle';
3636
if (priority === SupplyPriority.Remaining) return 'Disponível para doação';
3737
}

src/pages/CreateShelter/CreateShelter.tsx

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,63 @@ import {
1313
import { Header, TextField } from '@/components';
1414
import { Button } from '@/components/ui/button';
1515
import { ICreateShelter } from '@/service/shelter/types';
16+
import { toast } from '@/components/ui/use-toast';
17+
import { ShelterServices } from '@/service';
18+
import { withAuth } from '@/hocs';
1619

17-
const CreateShelter = () => {
20+
const CreateShelterComponent = () => {
1821
const navigate = useNavigate();
1922

20-
const verifySelected = (selected: string) => {
21-
if (selected === 'sim') return true;
22-
return false;
23-
};
24-
25-
const { errors, getFieldProps, isSubmitting, setFieldValue, handleSubmit } =
26-
useFormik<ICreateShelter>({
27-
initialValues: {
28-
name: '',
29-
address: '',
30-
shelteredPeople: 0,
31-
capacity: 0,
32-
petFriendly: false,
33-
contact: '',
34-
pix: '',
35-
},
36-
enableReinitialize: true,
37-
validateOnBlur: false,
38-
validateOnChange: false,
39-
validateOnMount: false,
40-
validationSchema: Yup.object().shape({
41-
name: Yup.string().required('Este campo deve ser preenchido'),
42-
address: Yup.string().required('Este campo deve ser preenchido'),
43-
}),
44-
onSubmit: async (values) => {
45-
//criar endpoint
46-
console.log(values);
47-
},
48-
});
23+
const {
24+
errors,
25+
getFieldProps,
26+
isSubmitting,
27+
setFieldValue,
28+
handleSubmit,
29+
values,
30+
} = useFormik<ICreateShelter>({
31+
initialValues: {
32+
name: '',
33+
address: '',
34+
shelteredPeople: 0,
35+
capacity: 0,
36+
petFriendly: false,
37+
contact: null,
38+
pix: null,
39+
},
40+
enableReinitialize: true,
41+
validateOnBlur: false,
42+
validateOnChange: false,
43+
validateOnMount: false,
44+
validationSchema: Yup.object().shape({
45+
name: Yup.string().required('Este campo deve ser preenchido'),
46+
address: Yup.string().required('Este campo deve ser preenchido'),
47+
shelteredPeople: Yup.number()
48+
.min(0, 'O valor mínimo para este campo é 0')
49+
.nullable(),
50+
capacity: Yup.number()
51+
.min(1, 'O valor mínimo para este campo é 1')
52+
.nullable(),
53+
petFriendly: Yup.bool().nullable(),
54+
contact: Yup.string().nullable(),
55+
pix: Yup.string().nullable(),
56+
}),
57+
onSubmit: async (values, { resetForm }) => {
58+
try {
59+
await ShelterServices.create(values);
60+
toast({
61+
title: 'Cadastro feita com sucesso',
62+
});
63+
resetForm();
64+
} catch (err: any) {
65+
toast({
66+
variant: 'destructive',
67+
title: 'Ocorreu um erro ao tentar cadastrar',
68+
description: `${err?.response?.data?.message ?? err}`,
69+
});
70+
}
71+
},
72+
});
4973

5074
return (
5175
<div className="flex flex-col h-screen items-center">
@@ -56,7 +80,7 @@ const CreateShelter = () => {
5680
<Button
5781
variant="ghost"
5882
className="[&_svg]:stroke-blue-500"
59-
onClick={() => navigate(-1)}
83+
onClick={() => navigate('/')}
6084
>
6185
<ChevronLeft size={20} />
6286
</Button>
@@ -75,54 +99,51 @@ const CreateShelter = () => {
7599
error={!!errors.name}
76100
helperText={errors.name}
77101
/>
78-
79102
<TextField
80103
label="Endereço do abrigo"
81104
{...getFieldProps('address')}
82105
error={!!errors.address}
83106
helperText={errors.address}
84107
/>
85-
86108
<TextField
87109
label="Contato"
88110
{...getFieldProps('contact')}
89111
error={!!errors.contact}
90112
helperText={errors.contact}
91113
/>
92-
93114
<TextField
94115
type="number"
116+
min="0"
95117
label="Quantidade de pessoas abrigadas"
96118
{...getFieldProps('shelteredPeople')}
97119
error={!!errors.shelteredPeople}
98120
helperText={errors.shelteredPeople}
99121
/>
100-
101122
<TextField
102123
type="number"
124+
min="0"
103125
label="Capacidade do abrigo"
104126
{...getFieldProps('capacity')}
105127
error={!!errors.capacity}
106128
helperText={errors.capacity}
107129
/>
108-
109130
<label className="text-muted-foreground">
110131
O abrigo aceita animais
111132
</label>
112133
<Select
134+
value={values.petFriendly ? 'true' : 'false'}
113135
onValueChange={(v) => {
114-
setFieldValue('petFriendly', verifySelected(v));
136+
setFieldValue('petFriendly', v === 'true');
115137
}}
116138
>
117139
<SelectTrigger className="w-full">
118140
<SelectValue className="text-muted-foreground" />
119141
</SelectTrigger>
120142
<SelectContent>
121-
<SelectItem value="sim">Sim</SelectItem>
122-
<SelectItem value="nao">Não</SelectItem>
143+
<SelectItem value="true">Sim</SelectItem>
144+
<SelectItem value="false">Não</SelectItem>
123145
</SelectContent>
124146
</Select>
125-
126147
<TextField
127148
label="Chave pix"
128149
{...getFieldProps('pix')}
@@ -145,4 +166,6 @@ const CreateShelter = () => {
145166
);
146167
};
147168

169+
const CreateShelter = withAuth(CreateShelterComponent);
170+
148171
export { CreateShelter };

src/pages/EditShelterSupply/EditShelterSupply.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,11 @@ const EditShelterSupply = () => {
118118
title="Escolha a prioridade do item"
119119
options={[
120120
{
121-
label: 'Necessita urgente',
121+
label: 'Precisa urgente',
122122
value: `${SupplyPriority.Urgent}`,
123123
},
124124
{
125-
label: 'Urgente',
125+
label: 'Precisa',
126126
value: `${SupplyPriority.Needing}`,
127127
},
128128
{

src/pages/Home/Home.tsx

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,29 @@
1-
import { Fragment, useCallback, useMemo, useState } from 'react';
2-
import { RotateCw, CircleAlert, Search, Loader } from 'lucide-react';
1+
import { Fragment, useCallback, useContext, useMemo, useState } from 'react';
2+
import {
3+
RotateCw,
4+
CircleAlert,
5+
Search,
6+
Loader,
7+
LogOutIcon,
8+
Heart,
9+
} from 'lucide-react';
310

411
import { Alert, Header, NoFoundSearch, ShelterListItem } from '@/components';
512
import { Input } from '@/components/ui/input';
613
import { useShelters, useThrottle } from '@/hooks';
714
import { Button } from '@/components/ui/button';
15+
import { SessionContext } from '@/contexts';
816

917
const alertDescription =
1018
'Você pode consultar a lista de abrigos disponíveis. Ver e editar os itens que necessitam de doações.';
1119

1220
const Home = () => {
1321
const { data: shelters, loading, refresh } = useShelters();
22+
const {
23+
loading: loadingSession,
24+
refreshSession,
25+
session,
26+
} = useContext(SessionContext);
1427
const [searchValue, setSearchValue] = useState<string>('');
1528
const [, setSearch] = useThrottle<string>(
1629
{
@@ -57,15 +70,36 @@ const Home = () => {
5770
<Header
5871
title="SOS Rio Grande do Sul"
5972
endAdornment={
60-
<Button
61-
loading={loading}
62-
variant="ghost"
63-
size="sm"
64-
onClick={() => refresh()}
65-
className="disabled:bg-red-500 hover:bg-red-400"
66-
>
67-
<RotateCw size={20} className="stroke-white" />
68-
</Button>
73+
<div className="flex gap-2 items-center">
74+
{session && (
75+
<h3 className="text-gray-300 font-thin">
76+
Bem vindo, {session.name}
77+
</h3>
78+
)}
79+
<Button
80+
loading={loading}
81+
variant="ghost"
82+
size="sm"
83+
onClick={() => refresh()}
84+
className="disabled:bg-red-500 hover:bg-red-400"
85+
>
86+
<RotateCw size={20} className="stroke-white" />
87+
</Button>
88+
{session && (
89+
<Button
90+
loading={loadingSession}
91+
variant="ghost"
92+
size="sm"
93+
onClick={() => {
94+
localStorage.removeItem('token');
95+
refreshSession();
96+
}}
97+
className="disabled:bg-red-500 hover:bg-red-400"
98+
>
99+
<LogOutIcon size={20} className="stroke-white" />
100+
</Button>
101+
)}
102+
</div>
69103
}
70104
/>
71105
<div className="p-5 gap-3 flex flex-col w-full max-w-5xl">
@@ -120,6 +154,30 @@ const Home = () => {
120154
)}
121155
</main>
122156
</div>
157+
<div className="w-full p-4 flex gap-3 justify-center p-4 flex-wrap items-center bg-red-600">
158+
<p className="text-white">
159+
Para cadastrar novos abrigos clique{' '}
160+
<a
161+
href="https://forms.gle/2S7L2gR529Dc8P3T9"
162+
className="underline hover:text-gray-300"
163+
target="_blank"
164+
>
165+
aqui
166+
</a>
167+
</p>
168+
<span className="text-white"></span>
169+
<p className="text-white flex flex-nowrap items-center gap-2">
170+
Projeto Open Source disponível em{' '}
171+
<a
172+
className="underline hover:text-gray-300"
173+
href="https://github.com/SOS-RS"
174+
target="_blank"
175+
>
176+
Github
177+
</a>
178+
<Heart className="h-3 w-3 stroke-white fill-white" />
179+
</p>
180+
</div>
123181
</div>
124182
);
125183
};

0 commit comments

Comments
 (0)