Skip to content

Commit

Permalink
Merge pull request #21 from ateliware/feat/vehicle-service
Browse files Browse the repository at this point in the history
Feature :: Formulário para cadastro de veículos
  • Loading branch information
roderiano authored May 10, 2024
2 parents dae8ca9 + b2f272d commit de51a09
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 36 deletions.
41 changes: 41 additions & 0 deletions src/interfaces/Vehicles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export type Vehicle = {
uuid: string;
model: string;
color: string;
plate: string;
platePicture: string;
vehiclePicture: string;
isVerified: boolean;
};

export type RemoteVehicle = {
uuid: string;
model: string;
color: string;
plate: string;
plate_picture: string;
vehicle_picture: string;
is_verified: boolean;
};

export type VehicleFormParams = {
cnh: string;
model: string;
color: string;
plate: string;
platePicture: File;
vehiclePicture: File;
cnhPicture: File;
isVerified: boolean;
};

export type RemoteVehicleFormParams = {
cnh_number: string;
model: string;
color: string;
plate: string;
plate_picture: string;
vehicle_picture: string;
cnh_picture: string;
is_verified: boolean;
};
22 changes: 18 additions & 4 deletions src/pages/RideOfferPage/RideOffer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';

Expand All @@ -12,21 +12,34 @@ import {
Select,
} from '@components';
import { useAuthContext } from '@contexts/AuthProvider';
import { Vehicle } from 'interfaces/Vehicles';
import VehiclesAPICaller from '@services/api/vehicles';

export default function RideOfferPage() {
const {
register,
handleSubmit,
formState: { errors, isSubmitting },
} = useForm();
const { user, isLoadingRequest } = useAuthContext();
const { user } = useAuthContext();
const navigate = useNavigate();

const [vehicles, setVehicles] = useState<Vehicle[]>([]);

useEffect(() => {
if (!!user) navigate('/home');
return;
}, [user, navigate]);

useEffect(() => {
VehiclesAPICaller.loadVehicles().then((vehicles) => {
setVehicles(vehicles);
if (!vehicles.length) {
navigate('/vehicle/add');
}
});
}, [navigate]);

const onSubmit = ((data: {
origin: string;
destination: string;
Expand All @@ -41,13 +54,14 @@ export default function RideOfferPage() {
return (
<div className="">
<PageHeader title="Ofertar carona" backButton={true}></PageHeader>

<ItemList
items={[
<>
<Item
key="volunteer"
title={'Modelo Veículo'}
description={'Marca / Placa'}
title={`${vehicles[0]?.model} - ${vehicles[0]?.color}`}
description={`${vehicles[0]?.plate}`}
icon={'directions_car'}
/>
</>,
Expand Down
106 changes: 75 additions & 31 deletions src/pages/Vehicle/VehicleForm.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';

import { Button, FileUpload, Input, PageHeader } from '@components';
import { toast } from 'react-toastify';

type VehicleFormParams = {
cnh: string;
brand: string;
model: string;
color: string;
cnhPhoto: File;
emergencyNome: string;
emergencyPhone: string;
};
import { Button, FileUpload, Input, PageHeader } from '@components';
import { VehicleFormParams } from 'interfaces/Vehicles';
import VehiclesAPICaller from '@services/api/vehicles';

export default function VehicleFormPage() {
const [file, setFile] = useState<File>();
const [fileError, setFileError] = useState<string>('');
const [platePicture, setPlatePicture] = useState<File>();
const [vehiclePicture, setvehiclePicture] = useState<File>();
const [cnhPicture, setCnhPicture] = useState<File>();

const {
register,
Expand All @@ -25,14 +20,34 @@ export default function VehicleFormPage() {
} = useForm();
const navigate = useNavigate();

useEffect(() => {
VehiclesAPICaller.loadVehicles().then((vehicles) => {
if (vehicles.length) {
navigate('/ride_offer');
}
});
}, [navigate]);

const onSubmit = async (data: VehicleFormParams) => {
if (!file) {
setFileError('Anexe uma foto da CNH');
if (!platePicture || !vehiclePicture || !cnhPicture) {
toast.error('Por favor, anexe as fotos necessárias!');
return;
}

data = { ...data, cnhPhoto: file };
console.log(data);
VehiclesAPICaller.registerVehicle({
...data,
platePicture,
vehiclePicture,
cnhPicture,
isVerified: false,
})
.then(() => {
toast.success('Veículo cadastrado com sucesso!');
navigate('/ride_offer');
})
.catch(() => {
toast.error('Erro ao cadastrar veículo!');
});
};

return (
Expand Down Expand Up @@ -65,14 +80,18 @@ export default function VehicleFormPage() {
caption={errors.cnh?.message as string}
mask="onlyNumbers"
/>

<Input
className="mb-s-200 mt-s-200"
form={register('brand', { required: 'Obrigatório' })}
label="Marca do carro"
placeholder="Marca do carro"
error={!!errors.brand}
caption={errors.brand?.message as string}
form={register('plate', {
required: 'Obrigatório',
})}
label="Placa do veículo"
placeholder="Placa do veículo"
error={!!errors.plate}
caption={errors.plate?.message as string}
/>

<Input
className="mb-s-200 mt-s-200"
form={register('model', { required: 'Obrigatório' })}
Expand All @@ -81,6 +100,7 @@ export default function VehicleFormPage() {
error={!!errors.model}
caption={errors.model?.message as string}
/>

<Input
className="mb-s-200 mt-s-200"
form={register('color', { required: 'Obrigatório' })}
Expand All @@ -91,24 +111,48 @@ export default function VehicleFormPage() {
/>

<FileUpload
label="Anexar foto da CNH"
label="Anexar foto da Placa do Veículo"
uploadPreview={true}
accept="image/*"
multiple={false}
maxSizeInBytes={2097152}
onChange={([file]) => {
if (file) {
setFileError('');
setFile(file);
setPlatePicture(file);
}
}}
/>

{fileError && (
<p className="text-left text-negative pt-s-100 font-s-100">
{fileError}
</p>
)}
<div className="mb-s-200 mt-s-200">
<FileUpload
label="Anexar foto do Veículo"
uploadPreview={true}
accept="image/*"
multiple={false}
maxSizeInBytes={2097152}
onChange={([file]) => {
if (file) {
setvehiclePicture(file);
}
}}
/>
</div>

<div className="mb-s-200 mt-s-200">
<FileUpload
className="mb-s-200 mt-s-200"
label="Anexar foto da CNH"
uploadPreview={true}
accept="image/*"
multiple={false}
maxSizeInBytes={2097152}
onChange={([file]) => {
if (file) {
setCnhPicture(file);
}
}}
/>
</div>

<hr className="mt-s-400 w-100 bg-neutral-60" />

Expand All @@ -134,7 +178,7 @@ export default function VehicleFormPage() {
alignText="center"
size="small"
>
Confirmar
Cadastrar
</Button>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/services/api/cities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class CitiesAPICaller {
const city = await retrieve<RemoteCity>(id);

return {
...city,
...city.data,
isActive: city.data.is_active,
};
};
Expand Down
13 changes: 13 additions & 0 deletions src/services/api/vehicles/calls.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { api } from '..';

export const list = async <T>() => {
return api.get<T>('/vehicles/');
};

export const retrieve = async <T>(id: string) => {
return api.get<T>(`/vehicles/${id}/`);
};

export const create = async <T>(data: T) => {
return api.post('/vehicles/', data);
};
48 changes: 48 additions & 0 deletions src/services/api/vehicles/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
RemoteVehicle,
RemoteVehicleFormParams,
VehicleFormParams,
} from 'interfaces/Vehicles';
import { create, list, retrieve } from './calls';
import { convertToBase64 } from '@utils/file/file';

export * from './calls';

export default class VehiclesAPICaller {
static loadVehicles = async () => {
const vehicles = await list<RemoteVehicle[]>();

return vehicles.data.map((vehicle) => ({
...vehicle,
isVerified: vehicle.is_verified,
platePicture: vehicle.plate_picture,
vehiclePicture: vehicle.vehicle_picture,
}));
};

static loadVehicleById = async (id: string) => {
const vehicle = await retrieve<RemoteVehicle>(id);

return {
...vehicle.data,
isVerified: vehicle.data.is_verified,
platePicture: vehicle.data.plate_picture,
vehiclePicture: vehicle.data.vehicle_picture,
};
};

static registerVehicle = async (data: VehicleFormParams) => {
const platePictureBase64 = await convertToBase64(data.platePicture);
const vehiclePictureBase64 = await convertToBase64(data.vehiclePicture);
const cnhPictureBase64 = await convertToBase64(data.cnhPicture);

await create<RemoteVehicleFormParams>({
...data,
cnh_number: data.cnh,
plate_picture: platePictureBase64,
vehicle_picture: vehiclePictureBase64,
cnh_picture: cnhPictureBase64,
is_verified: data.isVerified,
});
};
}

0 comments on commit de51a09

Please sign in to comment.