Skip to content

Commit

Permalink
final create post
Browse files Browse the repository at this point in the history
  • Loading branch information
IslemMedjahdi committed Jan 7, 2023
1 parent a5eb23b commit 9df3150
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"react-datepicker": "^4.8.0",
"react-dom": "18.2.0",
"react-icons": "^4.7.1",
"react-image-picker-editor": "^1.2.0",
"react-loader-spinner": "^5.3.4",
"react-quill": "^2.0.0",
"react-range": "^1.8.14",
Expand Down
126 changes: 123 additions & 3 deletions src/components/announcements/add-announcement/AddAnnouncementIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,49 @@
import dynamic from "next/dynamic";
import { useState } from "react";
import { useRouter } from "next/router";
import React, { useState } from "react";
import { ImagePickerConf } from "react-image-picker-editor";
import "react-image-picker-editor/dist/index.css";
import "react-quill/dist/quill.snow.css";
import { ICONS } from "../../../constants/icons";
import { INFO } from "../../../constants/info";
import { ROUTES } from "../../../constants/routes";

import { WILAYAS_FR } from "../../../constants/wilaya_algeria";
import AnnouncementService from "../../../services/annoucement.service";
import LocationService from "../../../services/locations.service";
import { Announcement } from "../../../typings/announcement";
import Select from "../../shared/Select";
import TextInput from "../../shared/TextInput";

const ReactQuill = dynamic(() => import("react-quill"), { ssr: false });
const ReactImagePickerEditor = dynamic(
() => import("react-image-picker-editor"),
{ ssr: false }
);

const locationService = LocationService.getInstance();
const announcementService = AnnouncementService.getInstance();

const config2: ImagePickerConf = {
borderRadius: "8px",
language: "en",
width: "100%",
height: "8rem",
objectFit: "cover",
compressInitial: null,
hideEditBtn: true,
hideDownloadBtn: true,
hideAddBtn: true,
};

const AddAnnouncementIndex = () => {
const router = useRouter();

const [announcement, setAnnouncement] =
useState<Announcement.AnnouncementNew>({});
const [photos, setPhotos] = useState<(Blob | null)[]>([]);
const [communes, setCommunes] = useState<string[]>([]);
const [loading, setLoading] = useState(false);

const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setAnnouncement((prev) => ({ ...prev, [e.target.name]: e.target.value }));
Expand All @@ -37,6 +64,49 @@ const AddAnnouncementIndex = () => {
}
};

const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (
!announcement.titre ||
!announcement.description ||
!announcement.adresse ||
!announcement.categorie ||
!announcement.type ||
!announcement.commune ||
!announcement.wilaya ||
!announcement.surface ||
!announcement.prix
) {
return;
}
setLoading(true);
const bodyFormData = new FormData();
bodyFormData.append("titre", announcement.titre);
bodyFormData.append("description", announcement.description);
bodyFormData.append("adresse", announcement.adresse);
bodyFormData.append("categorie", announcement.categorie);
bodyFormData.append("type", announcement.type);
bodyFormData.append("wilaya", announcement.wilaya);
bodyFormData.append("commune", announcement.commune);
bodyFormData.append("surface", announcement.surface.toString());
bodyFormData.append("prix", announcement.prix.toString());
photos.forEach(async (photo, index) => {
if (photo) {
bodyFormData.append("photos", photo, `image${index}.jpg`);
}
});
try {
const response = await announcementService.createAnnouncement(
bodyFormData
);
router.push(ROUTES.POSTED_ANNOUNCEMENTS.path);
} catch (e) {
console.log(e);
} finally {
setLoading(false);
}
};

return (
<div className="flex justify-center">
<div className="container px-4">
Expand All @@ -45,7 +115,7 @@ const AddAnnouncementIndex = () => {
Création d'une annonce
</h1>
</div>
<div className="w-full bg-white shadow">
<form onSubmit={onSubmit} className="w-full bg-white shadow">
<div className="flex flex-col gap-y-4 p-4">
<h1 className="flex items-center gap-x-2 font-serif text-sm font-medium text-gray-600">
<ICONS.Category />
Expand Down Expand Up @@ -137,6 +207,34 @@ const AddAnnouncementIndex = () => {
}
/>
</div>
<div>
<label
htmlFor={"description"}
className="flex items-center gap-x-1 text-sm font-medium text-gray-600 "
>
<span>Photos</span>
<span className="text-red-500">*</span>
</label>
<div className="mt-2 flex flex-wrap items-center justify-center gap-4 md:justify-start">
{[0, 1, 2, 3].map((item) => (
<div className="w-full max-w-[12rem] grow" key={item}>
<ReactImagePickerEditor
config={config2}
imageChanged={async (newDataUri: any) => {
const blob = newDataUri
? await (await fetch(newDataUri)).blob()
: null;
setPhotos((prev) => {
let newPhotos = [...prev];
newPhotos[item] = blob;
return newPhotos;
});
}}
/>
</div>
))}
</div>
</div>
<hr></hr>
<h1 className="flex items-center gap-x-2 font-serif text-sm font-medium text-gray-600">
<ICONS.Map />
Expand Down Expand Up @@ -178,7 +276,29 @@ const AddAnnouncementIndex = () => {
Icon={ICONS.Map}
/>
</div>
</div>
<hr />
<div className="flex justify-end p-4">
<button
disabled={
!announcement.titre ||
!announcement.description ||
!announcement.adresse ||
!announcement.categorie ||
!announcement.type ||
!announcement.commune ||
!announcement.wilaya ||
!announcement.surface ||
!announcement.prix
}
type="submit"
className={`${
loading ? "animate-pulse" : ""
} rounded-sm bg-blue-primary px-6 py-2 text-sm font-medium text-white transition duration-200 hover:bg-blue-hover disabled:bg-blue-hover`}
>
Envoyer
</button>
</div>
</form>
</div>
</div>
);
Expand Down
13 changes: 13 additions & 0 deletions src/services/annoucement.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ class AnnouncementService {
}
}

public async createAnnouncement(data: FormData) {
try {
const response = await axios.postForm("/announcements/create", data, {
headers: {
"Content-Type": "multipart/form-data",
},
});
return response;
} catch (e) {
throw e;
}
}

public async getAnnouncementById(id: number) {
try {
const response = await axios.get(`/announcements/${id}`);
Expand Down
11 changes: 10 additions & 1 deletion src/typings/announcement.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@ declare module Announcement {
type AnnouncementPart = Omit<Announcement, "fans" | "auteur" | "messages">;

type AnnouncementNew = Partial<
Omit<Announcement, "id" | "messages" | "localisation" | "photos"> &
Omit<
Announcement,
| "id"
| "messages"
| "localisation"
| "photos"
| "fans"
| "auteur"
| "date_publication"
> &
Omit<Commun.Localisation, "id">
>;

Expand Down
19 changes: 19 additions & 0 deletions src/utils/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,22 @@ export const formatDate = (date: Date) => {

return [year, month, day].join("-");
};

export function dataURItoBlob(dataURI: string) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(",")[0].indexOf("base64") >= 0)
byteString = atob(dataURI.split(",")[1]);
else byteString = unescape(dataURI.split(",")[1]);

// separate out the mime component
var mimeString = dataURI.split(",")[0].split(":")[1].split(";")[0];

// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}

return new Blob([ia], { type: mimeString });
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2315,6 +2315,11 @@ react-icons@^4.7.1:
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345"
integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw==

react-image-picker-editor@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/react-image-picker-editor/-/react-image-picker-editor-1.2.0.tgz#5185145f79a8f0b6c5b26751ecf59fff4707baff"
integrity sha512-ASl8QFQRPPepB7vA6phe8lTzNYrVysgNJiWuNHiMQAVBh7I0qacJsNG9ByBolywLqM3ofcFksYLhj/yGks/nxg==

react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand Down

0 comments on commit 9df3150

Please sign in to comment.