├── .gitignore
├── 1.PNG
├── 1.jpg
├── 10.PNG
├── 2.PNG
├── 3.PNG
├── 4.PNG
├── 5.PNG
├── 6.png
├── 7.png
├── README.md
├── ca.jpg
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── si.jpg
├── src
├── App.js
├── App.sass
├── assets
│ ├── Rented.png
│ ├── client.png
│ ├── h2.png
│ ├── h3.svg
│ ├── host.png
│ └── q.svg
├── components
│ ├── about.js
│ ├── admin
│ │ ├── adminHome.js
│ │ ├── adminLayout.js
│ │ ├── adminPosts.js
│ │ └── adminUsers.js
│ ├── agent
│ │ ├── agentHome.js
│ │ └── agentLayout.js
│ ├── auth
│ │ ├── forget.js
│ │ ├── login.js
│ │ ├── reset.js
│ │ ├── signup_client.js
│ │ └── signup_host.js
│ ├── client
│ │ └── profile.js
│ ├── host
│ │ ├── dashboardCopoments
│ │ │ ├── Posts.js
│ │ │ └── Slider
│ │ │ │ └── BtnSlider.js
│ │ ├── hostHome.js
│ │ ├── hostLayout.js
│ │ ├── hostPosts.js
│ │ └── reservations.js
│ ├── products
│ │ ├── details.js
│ │ └── search.js
│ └── utilities
│ │ └── Navbar.js
├── config
│ └── fbConfig.js
├── index.js
├── state
│ ├── auth_slice.js
│ └── store.js
└── styles
│ ├── Admin.sass
│ ├── Slider.sass
│ ├── _variables.sass
│ ├── dashboardCompoments
│ ├── Dashboard.sass
│ └── Posts.sass
│ ├── details.sass
│ ├── login.sass
│ ├── navbar.sass
│ ├── profile.sass
│ ├── search.sass
│ └── signup.sass
└── tailwind.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/1.PNG
--------------------------------------------------------------------------------
/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/1.jpg
--------------------------------------------------------------------------------
/10.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/10.PNG
--------------------------------------------------------------------------------
/2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/2.PNG
--------------------------------------------------------------------------------
/3.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/3.PNG
--------------------------------------------------------------------------------
/4.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/4.PNG
--------------------------------------------------------------------------------
/5.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/5.PNG
--------------------------------------------------------------------------------
/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/6.png
--------------------------------------------------------------------------------
/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/7.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | RENTED
3 | ===
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | ## Summary :
17 | #### RENTED is a web app created to be a link between people searching for appartements to rent, and hosts. it provides confidential solutions to make renting easier then ever, created with the mern stack .
18 |
19 | [View project specifications !](https://www.canva.com/design/DAFDhx_rEnk/vQuHlD6T1Fswz2f0AcIeBw/view?utm_content=DAFDhx_rEnk&utm_campaign=designshare&utm_medium=link2&utm_source=sharebutton)
20 |
21 | [Get the backend Code !]( https://github.com/Merzouk-Ilyes/Projet-2CS-Back)
22 |
23 |
24 |
25 | ## How use this app as a developer
26 |
27 | ## Using Docker
28 | 1. git clone the repo
29 | 2. run docker compose-up
30 |
31 | ### Old way
32 | 1. git clone
33 | 2. npm install for all the repositories
34 | 3. run all project repos
35 | 4. run the reduis server (use wsl for windows)
36 |
37 | if you have any question don't hesitate to ask :+1:
38 |
39 | User story
40 | ---
41 |
42 | ```gherkin=
43 | As a client, I can serve the website.
44 | As a client, I can reserve an appartement
45 | As a client, I can search appartements
46 | As a client, I can view or cancel my reservations
47 | As a client, I can upgrade to host
48 |
49 | ```
50 | ```gherkin=
51 | As a host, I can post new locations
52 | As a host, I can accept or refuse reservation requests
53 | As a host, I can review my posts hystory
54 | As a host, I can report a client
55 |
56 |
57 | ```
58 | ```gherkin=
59 | As an admin, I can manage accounts , validate or delete accounts
60 | As an admin, I can view my daily , weekly and monthly statistics.
61 | As an admin, I can assign post to agents and verify posts.
62 |
63 | ```
64 |
65 | ### general use case diagram :
66 |
67 |
68 |
69 |
70 |
71 | ## architecture schema
72 | we used microservices in this project , Microservices refer to both an architecture and a software development approach that consists of breaking down applications into the simplest elements, independent of each other.
73 |
74 |
75 |
76 |
77 | ## Our recomendations
78 | we used a js library that uses the KNN algorithme for a Collaborative Filtering Recommendation system
79 |
80 |
81 |
82 |
83 |
84 | Used Technology
85 | ---
86 |
87 |
88 | 
89 | 
90 | 
91 |
92 | 
93 | 
94 | 
95 | 
96 | 
97 |
98 |
99 |
100 |
101 | availble roles
102 | ---
103 | 1. client
104 | 2. host
105 | 3. agent
106 | 4. admin
107 |
108 | Rented provides
109 | ---
110 | - reservation gesture
111 | - accounts gesture
112 | - posts gesture
113 | - recommendation gesture
114 |
115 | ---
116 | ---
117 | If you liked the repo then kindly support it by giving it a star ⭐ and share in your circles so more people can benefit from the effort.
118 |
119 | ## Contributions Welcome
120 | [](#)
121 |
122 | If you find any bug in the code or have any improvements in mind then feel free to generate a pull request.
123 |
124 | ## Issues
125 |
126 | [](https://github.com/Merzouk-Ilyes/Projet-2CS-Front/issues)
127 |
128 | If you face any issue, you can create a new issue in the Issues Tab and I will be glad to help you out.
129 |
130 |
131 |
132 |
133 | ## Contributors
134 |
135 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/ca.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/ca.jpg
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@chakra-ui/react": "^1.8.7",
7 | "@emotion/react": "^11.8.2",
8 | "@emotion/styled": "^11.8.1",
9 | "@iconscout/react-unicons": "^1.1.6",
10 | "@reduxjs/toolkit": "^1.8.1",
11 | "@testing-library/jest-dom": "^5.16.3",
12 | "@testing-library/react": "^12.1.4",
13 | "@testing-library/user-event": "^13.5.0",
14 | "axios": "^0.26.1",
15 | "date-fns": "^2.28.0",
16 | "firebase": "^9.8.1",
17 | "framer-motion": "^6.2.8",
18 | "moment": "^2.29.3",
19 | "node-sass": "^7.0.1",
20 | "react": "^17.0.2",
21 | "react-custom-checkbox": "^2.0.1",
22 | "react-date-range": "^1.4.0",
23 | "react-dom": "^17.0.2",
24 | "react-icons": "^4.3.1",
25 | "react-loading-skeleton": "^3.1.0",
26 | "react-redux": "^7.2.8",
27 | "react-router-dom": "^6.2.2",
28 | "react-scripts": "5.0.0",
29 | "react-toastify": "^8.2.0",
30 | "reactstrap": "^9.0.2",
31 | "web-vitals": "^2.1.4"
32 | },
33 | "scripts": {
34 | "start": "react-scripts start",
35 | "build": "react-scripts build",
36 | "test": "react-scripts test",
37 | "eject": "react-scripts eject"
38 | },
39 | "eslintConfig": {
40 | "extends": [
41 | "react-app",
42 | "react-app/jest"
43 | ]
44 | },
45 | "browserslist": {
46 | "production": [
47 | ">0.2%",
48 | "not dead",
49 | "not op_mini all"
50 | ],
51 | "development": [
52 | "last 1 chrome version",
53 | "last 1 firefox version",
54 | "last 1 safari version"
55 | ]
56 | },
57 | "devDependencies": {
58 | "autoprefixer": "^10.4.7",
59 | "postcss": "^8.4.13",
60 | "tailwindcss": "^3.0.24"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
22 |
23 |
32 |
33 |
34 |
38 | React App
39 |
40 |
41 |
42 |
43 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/si.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/si.jpg
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.sass';
2 |
3 |
4 | function App() {
5 | return (
6 |
7 | Landing page
8 |
9 | );
10 | }
11 |
12 | export default App;
13 |
--------------------------------------------------------------------------------
/src/App.sass:
--------------------------------------------------------------------------------
1 | @tailwind base
2 | @tailwind components
3 | @tailwind utilities
4 | html,*
5 | box-sizing: border-box
6 | margin: 0
7 | padding: 0
8 | text-decoration: none
9 | font-family: 'Raleway', sans-serif;
--------------------------------------------------------------------------------
/src/assets/Rented.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/src/assets/Rented.png
--------------------------------------------------------------------------------
/src/assets/client.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/src/assets/client.png
--------------------------------------------------------------------------------
/src/assets/h2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/src/assets/h2.png
--------------------------------------------------------------------------------
/src/assets/host.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Merzouk-Ilyes/Projet-2CS-Front/d2b7a01b5865f5800757c1d51da754a2e2974871/src/assets/host.png
--------------------------------------------------------------------------------
/src/components/about.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | function About() {
4 | return (
5 | About
6 | )
7 | }
8 |
9 | export default About
--------------------------------------------------------------------------------
/src/components/admin/adminHome.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SidebarWithHeader from "./adminLayout"
3 |
4 | function Admin() {
5 | return (
6 |
7 |
8 | admin
9 |
10 | );
11 | }
12 |
13 | export default Admin;
14 |
--------------------------------------------------------------------------------
/src/components/admin/adminLayout.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | IconButton,
4 | Avatar,
5 | Box,
6 | CloseButton,
7 | Flex,
8 | HStack,
9 | VStack,
10 | Icon,
11 | useColorModeValue,
12 | Link,
13 | Drawer,
14 | DrawerContent,
15 | Text,
16 | useDisclosure,
17 | BoxProps,
18 | FlexProps,
19 | Menu,
20 | MenuButton,
21 | MenuDivider,
22 | MenuItem,
23 | MenuList,
24 | } from "@chakra-ui/react";
25 | import { FiHome, FiMenu, FiChevronDown,FiUsers } from "react-icons/fi";
26 | import {
27 | BsCalendarCheck,
28 | BsBell,
29 | BsPatchCheck,
30 | BsPatchExclamation,
31 | } from "react-icons/bs";
32 | import { BiTimeFive } from "react-icons/bi";
33 | import { Link as reactRouter } from "react-router-dom";
34 | import { MdPublic } from "react-icons/md";
35 | import logo from "../../assets/Rented.png";
36 |
37 | const LinkItems = [
38 | { name: "Home", icon: FiHome, path: "/admin" },
39 | { name: "Posts", icon: MdPublic, path: "/admin/posts" },
40 | { name: "Users", icon: FiUsers, path: "/admin/users" },
41 | ];
42 |
43 | export default function SidebarWithHeader({ children }) {
44 | const { isOpen, onOpen, onClose } = useDisclosure();
45 | return (
46 |
47 | onClose}
49 | display={{ base: "none", md: "block" }}
50 | />
51 |
60 |
61 |
62 |
63 |
64 | {/* mobilenav */}
65 |
66 |
67 | {children}
68 |
69 |
70 | );
71 | }
72 |
73 | const SidebarContent = ({ onClose, ...rest }) => {
74 | return (
75 |
85 |
86 |
87 |

88 |
89 |
90 |
91 | {LinkItems.map((link) => (
92 |
93 | {link.name}
94 |
95 | ))}
96 |
97 | );
98 | };
99 |
100 | const NavItem = ({ icon, children, path, ...rest }) => {
101 | return (
102 |
108 |
121 | {icon && (
122 |
130 | )}
131 | {children}
132 |
133 |
134 | );
135 | };
136 |
137 | const MobileNav = ({ onOpen, ...rest }) => {
138 | return (
139 |
150 | }
156 | />
157 |
158 |
159 |

160 |
161 |
162 |
163 |
164 |
192 |
193 |
228 |
229 |
230 |
231 | );
232 | };
233 |
234 | const NotificationItem = ({ notif, iconType }) => {
235 | if (iconType == 1) {
236 | return (
237 |
241 | );
242 | } else if (iconType == 2) {
243 | return (
244 |
248 | );
249 | } else if (iconType == 3) {
250 | return (
251 |
255 | );
256 | } else if (iconType == 4) {
257 | return (
258 |
262 | );
263 | } else
264 | return (
265 |
269 | );
270 | };
271 |
--------------------------------------------------------------------------------
/src/components/admin/adminUsers.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import SidebarWithHeader from "./adminLayout";
3 | import {
4 | Menu,
5 | MenuButton,
6 | MenuList,
7 | MenuItem,
8 | IconButton,
9 | Avatar,
10 | Button,
11 | Modal,
12 | ModalOverlay,
13 | ModalContent,
14 | ModalHeader,
15 | ModalFooter,
16 | ModalBody,
17 | ModalCloseButton,
18 | useDisclosure,
19 | Spinner,
20 | } from "@chakra-ui/react";
21 | import {HiOutlineIdentification} from "react-icons/hi"
22 | import { BsThreeDotsVertical } from "react-icons/bs";
23 | import { AiOutlineDelete, AiOutlineThunderbolt } from "react-icons/ai";
24 | import { GrValidate } from "react-icons/gr";
25 | import axios from "axios";
26 | import { toast } from "react-toastify";
27 |
28 | function AdminUsers() {
29 | const [users, setUsers] = useState([]);
30 | const [loading, setLoading] = useState(true);
31 | const url = "http://localhost:8000/accounts";
32 | useEffect(() => {
33 | getUsers();
34 | }, []);
35 | const getUsers = () => {
36 | axios
37 | .get(url)
38 | .then((response) => {
39 | const users = response.data;
40 | setUsers(users);
41 | setLoading(false);
42 | console.log("users =>" + JSON.stringify(users[0].emailVerified));
43 | })
44 | .catch((err) => {
45 | console.log(err);
46 | });
47 | };
48 |
49 | return (
50 |
51 |
52 |
53 |
Users
54 |
55 |
56 |
57 |
58 |
59 |
60 | User
61 | |
62 |
63 | Email
64 | |
65 |
66 | Phone number
67 | |
68 |
69 | Role
70 | |
71 |
72 | Email Verified
73 | |
74 |
75 | Account verified
76 | |
77 | |
78 |
79 |
80 |
81 | {loading ? (
82 |
83 |
84 |
85 | |
86 |
87 | ) : (
88 | users.map((users, i) => (
89 |
99 | ))
100 | )}
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | );
109 | }
110 |
111 | export default AdminUsers;
112 |
113 | const TableItem = ({
114 | name,
115 | email,
116 | type,
117 | emailVerified,
118 | accountVerified,
119 | phone,idUser
120 | }) => {
121 | var role = "Client";
122 | if (type == 0) {
123 | role = "Admin";
124 | } else if (type == 1) {
125 | role = "Agent";
126 | } else if (type == 2) {
127 | role = "Client";
128 | } else if (type == 3) {
129 | role = "Host";
130 | }
131 |
132 | return (
133 |
134 |
135 |
143 | |
144 |
145 | {email}
146 | |
147 |
148 | {phone}
149 | |
150 |
151 | {role}
152 | |
153 |
154 |
155 |
156 |
157 | |
158 |
159 |
160 |
161 |
162 | |
163 |
164 |
165 |
180 | |
181 |
182 | );
183 | };
184 | const DetailsMenuItem = ({id}) => {
185 | const { isOpen, onOpen, onClose } = useDisclosure();
186 | const url = "http://localhost:8000/validateAccount";
187 | const validateAccount = () => {
188 | axios
189 | .post(url,{id:id})
190 | .then((response) => {
191 | console.log(response);
192 | onClose();
193 | toast.success("Account is verified !");
194 | setTimeout(() => {
195 | window.location.reload(false);
196 | }, 2500);
197 |
198 |
199 | })
200 | .catch((err) => {
201 | console.log(err);
202 | });
203 | };
204 |
205 | return (
206 | } fontSize={18}>
207 | Validate Account
208 |
209 |
210 |
211 | Validate
212 |
213 | Are you sure you want to validate this account?
214 |
215 |
216 |
224 |
232 |
233 |
234 |
235 |
236 | );
237 | };
238 | const SeeId = () => {
239 | const { isOpen, onOpen, onClose } = useDisclosure();
240 |
241 |
242 | return (
243 | } fontSize={18}>
244 | Verify ID
245 |
246 |
247 |
248 | Validate
249 |
250 | Are you sure you want to validate this account?
251 |
252 |
253 |
261 |
269 |
270 |
271 |
272 |
273 | );
274 | };
275 |
276 | const DeleteMenuItem = () => {
277 | const { isOpen, onOpen, onClose } = useDisclosure();
278 |
279 | return (
280 | }
283 | fontSize={18}
284 | >
285 | Delete
286 |
287 |
288 |
289 | Delete
290 |
291 | Are you sure you want to delete this?
292 |
293 |
294 |
302 |
305 |
306 |
307 |
308 |
309 | );
310 | };
311 |
312 | const Status = ({ status }) => {
313 | var bgColor;
314 | var color;
315 | if (status) {
316 | bgColor = "bg-green-200";
317 | color = "text-green-900";
318 | } else {
319 | bgColor = "bg-red-200";
320 | color = "text-red-900";
321 | }
322 | return (
323 |
326 |
330 | {status ? "Verified" : "Not Verified"}
331 |
332 | );
333 | };
334 |
--------------------------------------------------------------------------------
/src/components/agent/agentHome.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import SidebarWithHeader from "./agentLayout";
3 | import {
4 | Badge,
5 | Button,
6 | Center,
7 | Flex,
8 | Heading,
9 | Image,
10 | Stack,
11 | Text,
12 | useDisclosure,
13 | Drawer,
14 | DrawerBody,
15 | DrawerHeader,
16 | DrawerOverlay,
17 | DrawerContent,
18 | DrawerCloseButton,
19 | Box,
20 | Container,
21 | VStack,
22 | SimpleGrid,
23 | StackDivider,
24 | List,
25 | ListItem,
26 | Textarea,
27 | Modal,
28 | ModalOverlay,
29 | ModalContent,
30 | ModalHeader,
31 | ModalFooter,
32 | ModalBody,
33 | Input,
34 | } from "@chakra-ui/react";
35 | import { BsCheck2Circle, BsSnow } from "react-icons/bs";
36 | import { FaCouch, FaWifi } from "react-icons/fa";
37 | import { MdKitchen, MdOutlineElectricalServices } from "react-icons/md";
38 | import { BiWater } from "react-icons/bi";
39 | import axios from "axios";
40 | // import { Page, Text as pdfText, View, Document, StyleSheet ,PDFDownloadLink} from '@react-pdf/renderer';
41 |
42 | function AgentHome() {
43 | const [posts, setPosts] = useState([]);
44 | const url = "http://localhost:8001/findAllPosts";
45 |
46 | useEffect(() => {
47 | getPosts();
48 | }, []);
49 | const getPosts = () => {
50 | axios
51 | .get(url)
52 | .then((response) => {
53 | const posts = response.data.result;
54 | setPosts(posts);
55 | console.log("posts =>" + posts);
56 | })
57 | .catch((err) => {
58 | console.log(err);
59 | });
60 | };
61 | return (
62 |
63 | Posts
64 |
65 | {posts.map((post, i) => (
66 |
78 | ))}
79 |
80 |
81 | );
82 | }
83 |
84 | export default AgentHome;
85 |
86 | function AgentPostCard({
87 | imageUrl,
88 | title,
89 | price,
90 | baths,
91 | beds,
92 | rating,
93 | verified,
94 | space,
95 | city,
96 | }) {
97 | const { isOpen, onOpen, onClose } = useDisclosure();
98 | return (
99 |
100 |
110 |
111 |
112 |
113 |
121 |
122 | {title}
123 | {verified ? (
124 |
132 |
133 |
134 | ) : (
135 | ""
136 | )}
137 |
138 |
139 | {city}
140 |
141 |
142 | {beds} BEDS • {baths} BATHS •{space} M°2
143 |
144 |
145 |
146 | $ {price}/ night
147 |
148 |
149 |
150 |
168 |
181 |
182 |
183 |
184 | );
185 | }
186 |
187 | function DetailsDrawer({
188 | onClose,
189 | isOpen,
190 | imageUrl,
191 | title,
192 | price,
193 | baths,
194 | beds,
195 | rating,
196 | verified,
197 | space,
198 | city,
199 | }) {
200 | return (
201 |
202 |
203 |
204 |
205 |
206 |
207 |
218 |
219 |
220 |
221 | );
222 | }
223 |
224 | function DetailsDrawerData({
225 | imageUrl,
226 | title,
227 | price,
228 | baths,
229 | beds,
230 | rating,
231 | verified,
232 | space,
233 | city,
234 | }) {
235 | const { isOpen, onOpen, onClose } = useDisclosure();
236 | const {isOpen: isFOpen,onOpen: onFOpen,onClose: onFClose } = useDisclosure();
237 |
238 | return (
239 |
240 |
245 |
246 |
255 |
256 |
257 |
258 |
263 | {title}
264 |
265 |
266 | ${price} /NIGHT
267 |
268 |
269 |
270 | }
274 | >
275 |
276 |
277 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed
278 | diam nonumy eirmod tempor invidunt ut labore
279 |
280 |
281 |
282 |
289 | Features
290 |
291 |
292 |
293 |
294 |
295 | Water
296 |
297 |
298 | Gas {" "}
299 |
300 |
301 |
302 | Electricity {" "}
303 |
304 |
305 |
306 |
307 | {" "}
308 | Furniture
309 |
310 |
311 | Wifi {" "}
312 |
313 |
314 | Air conditioning
315 |
316 |
317 |
318 |
319 |
320 |
327 | Post Details
328 |
329 |
330 |
331 |
332 |
333 | Local type:
334 | {" "}
335 | Villa
336 |
337 |
338 |
339 | City:
340 | {" "}
341 | {city}
342 |
343 |
344 |
345 | Street:
346 | {" "}
347 | Oran
348 |
349 |
350 |
351 | Number of beds:
352 | {" "}
353 | {beds}
354 |
355 |
356 |
357 | Number of baths:
358 | {" "}
359 | {baths}
360 |
361 |
362 |
363 | Space:
364 | {" "}
365 | {space} M°2
366 |
367 |
368 |
369 | Rating:
370 | {" "}
371 | {rating}
372 |
373 |
374 |
375 |
376 |
377 | {/*
} fileName="agent.pdf">
378 | {({ blob, url, loading, error }) =>
379 | loading ? 'Loading document...' : 'Download now!'
380 | }
381 | */}
382 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
412 |
413 |
414 |
415 |
416 |
417 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
449 |
450 |
451 |
452 |
453 | {/*
*/}
471 |
472 |
473 |
474 |
475 | );
476 | }
477 | // // Create styles
478 | // const styles = StyleSheet.create({
479 | // page: {
480 | // flexDirection: 'row',
481 | // backgroundColor: '#E4E4E4'
482 | // },
483 | // section: {
484 | // margin: 10,
485 | // padding: 10,
486 | // flexGrow: 1
487 | // }
488 | // });
489 |
490 | // // Create Document Component
491 | // const MyDoc = () => (
492 | //
493 | //
494 | //
495 | // Section #1
496 | //
497 | //
498 | // Section #2
499 | //
500 | //
501 | //
502 | // );
--------------------------------------------------------------------------------
/src/components/agent/agentLayout.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import {
3 | IconButton,
4 | Avatar,
5 | Box,
6 | CloseButton,
7 | Flex,
8 | HStack,
9 | VStack,
10 | Icon,
11 | useColorModeValue,
12 | Link,
13 | Drawer,
14 | DrawerContent,
15 | Text,
16 | useDisclosure,
17 | BoxProps,
18 | FlexProps,
19 | Menu,
20 | MenuButton,
21 | MenuDivider,
22 | MenuItem,
23 | MenuList,
24 | } from "@chakra-ui/react";
25 | import { FiHome, FiMenu, FiChevronDown } from "react-icons/fi";
26 | import {
27 | BsCalendarCheck,
28 | BsBell,
29 | BsPatchCheck,
30 | BsPatchExclamation,
31 | } from "react-icons/bs";
32 | import { BiTimeFive } from "react-icons/bi";
33 | import { Link as reactRouter } from "react-router-dom";
34 |
35 | const LinkItems = [
36 | { name: "Home", icon: FiHome, path: "/agent" },
37 |
38 | ];
39 |
40 | export default function SidebarWithHeader({ children }) {
41 | const { isOpen, onOpen, onClose } = useDisclosure();
42 | return (
43 |
44 | onClose}
46 | display={{ base: "none", md: "block" }}
47 | />
48 |
57 |
58 |
59 |
60 |
61 | {/* mobilenav */}
62 |
63 |
64 | {children}
65 |
66 |
67 | );
68 | }
69 |
70 | const SidebarContent = ({ onClose, ...rest }) => {
71 | return (
72 |
82 |
83 |
84 | Logo
85 |
86 |
87 |
88 | {LinkItems.map((link) => (
89 |
90 | {link.name}
91 |
92 | ))}
93 |
94 | );
95 | };
96 |
97 | const NavItem = ({ icon, children, path, ...rest }) => {
98 | return (
99 |
105 |
118 | {icon && (
119 |
127 | )}
128 | {children}
129 |
130 |
131 | );
132 | };
133 |
134 | const MobileNav = ({ onOpen, ...rest }) => {
135 | return (
136 |
147 | }
153 | />
154 |
155 |
161 | Logo
162 |
163 |
164 |
165 |
193 |
194 |
229 |
230 |
231 |
232 | );
233 | };
234 |
235 | const NotificationItem = ({ notif, iconType }) => {
236 | if (iconType == 1) {
237 | return (
238 |
242 | );
243 | } else if (iconType == 2) {
244 | return (
245 |
249 | );
250 | } else if (iconType == 3) {
251 | return (
252 |
256 | );
257 | } else if (iconType == 4) {
258 | return (
259 |
263 | );
264 | } else
265 | return (
266 |
270 | );
271 | };
272 |
--------------------------------------------------------------------------------
/src/components/auth/forget.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import '../../styles/login.sass'
3 | import axios from 'axios'
4 | import face from '../../assets/q.svg'
5 | import { Link } from 'react-router-dom'
6 | import Navbar from '../utilities/Navbar'
7 | import { toast } from 'react-toastify'
8 |
9 | function ForgetPassword() {
10 | const [loginData, setLoginData] = useState({
11 | email: '',
12 | })
13 |
14 | const handleSubmit = (e) => {
15 | e.preventDefault()
16 | axios
17 | .post('http://localhost:8000/forgetpass', {
18 | email: loginData.email,
19 | })
20 | .then((response) => {
21 | if (response.data.message) {
22 | toast.success(response.data.message)
23 | } else {
24 | toast.error(response.data.err)
25 | }
26 | })
27 | .catch((error) => console.log(error))
28 | }
29 | return (
30 | <>
31 |
32 |
33 |
34 |
Logo
35 |
36 |
Reset Password
37 |
56 |
57 |
58 |
59 | Want to log in ? Log in
60 |
61 |
62 |
63 |
64 |

65 |
66 |
67 | >
68 | )
69 | }
70 |
71 | export default ForgetPassword
72 |
--------------------------------------------------------------------------------
/src/components/auth/login.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import '../../styles/login.sass'
3 | import axios from 'axios'
4 | import face from '../../assets/h3.svg'
5 | import Navbar from '../utilities/Navbar'
6 | import { AiFillEye, AiFillEyeInvisible } from 'react-icons/ai'
7 | import { Link, useNavigate } from 'react-router-dom'
8 | import { toast } from 'react-toastify'
9 | import { actions } from '../../state/auth_slice'
10 | import { useDispatch, useSelector } from 'react-redux'
11 |
12 | function Login() {
13 | const [show, setShow] = useState(false)
14 | const handleClick = () => setShow(!show)
15 | let navigate = useNavigate()
16 | const dispatch = useDispatch()
17 | const isLogged = useSelector((state) => state.isLogged)
18 | console.log(isLogged)
19 | const [loginData, setLoginData] = useState({
20 | email: '',
21 | password: '',
22 | })
23 | //"http://localhost:7777/account/login"
24 | const handleSubmit = (e) => {
25 | e.preventDefault()
26 | console.log(loginData)
27 | axios
28 | .post('http://localhost:8000/login', {
29 | email: loginData.email,
30 | password: loginData.password,
31 | })
32 | .then((response) => {
33 |
34 |
35 | if (response.data.token) {
36 | toast.success('Login successful !')
37 | sessionStorage.setItem("USER", JSON.stringify(response.data.user));
38 | //Changing the isLogged state in the redux store
39 | dispatch(actions.setLogin(true))
40 | //Redirection arroding to user role
41 | if (response.data.user.role === 0) {
42 | setTimeout(() => {
43 | navigate('/admin')
44 | }, 2000)
45 | } else if (response.data.user.role === 1) {
46 | setTimeout(() => {
47 | navigate('/agent')
48 | }, 2000)
49 | } else if (response.data.user.role === 3) {
50 | setTimeout(() => {
51 | navigate('/host')
52 | }, 2000)
53 | } else {
54 | setTimeout(() => {
55 | navigate('/')
56 | }, 2000)
57 | }
58 | } else {
59 | toast.error(response.data.err)
60 | }
61 | })
62 | .catch((error) => console.log(error))
63 | }
64 | return (
65 | <>
66 |
67 |
68 |
69 |
Welcome back
70 |
117 |
118 |
119 |
120 | Don't have an account? Sign up
121 |
122 |
123 |
124 |
125 |

126 |
127 |
128 | >
129 | )
130 | }
131 |
132 | export default Login
133 |
--------------------------------------------------------------------------------
/src/components/auth/reset.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import '../../styles/login.sass'
3 | import face from '../../assets/q.svg'
4 | import Navbar from '../utilities/Navbar'
5 | import axios from 'axios'
6 | import { AiFillEye, AiFillEyeInvisible } from 'react-icons/ai'
7 | import { Link, useNavigate } from 'react-router-dom'
8 | import { toast } from 'react-toastify'
9 |
10 | function ResetPwd() {
11 | const [show, setShow] = React.useState(false)
12 | const [show2, setShow2] = React.useState(false)
13 | const handleClick = () => setShow(!show)
14 | const handleClick2 = () => setShow2(!show2)
15 | let navigate = useNavigate()
16 |
17 | const [resetData, setResetData] = useState({
18 | password: '',
19 | password2: '',
20 | })
21 |
22 | const handleSubmit = (e) => {
23 | e.preventDefault()
24 | const queryParams = new URLSearchParams(window.location.search)
25 | const id = queryParams.get('id')
26 | const token = queryParams.get('token')
27 |
28 | if (resetData.password !== resetData.password2) {
29 | toast.error('confirm your password correctly')
30 | return
31 | }
32 |
33 | axios
34 | .post(`http://localhost:8000/resetpass/${id}/${token}`, {
35 | password: resetData.password,
36 | })
37 | .then((response) => {
38 | if (response.data.message) {
39 | toast.success(response.data.message)
40 | setTimeout(() => {
41 | navigate('/login')
42 | }, 2500)
43 | } else {
44 | toast.error('there was an error')
45 | }
46 | })
47 | .catch((error) => console.log(error))
48 | }
49 | return (
50 | <>
51 |
52 |
53 |
54 |
Logo
55 |
56 |
Reset Password
57 |
114 |
115 |
116 |
117 | Want to log in ? Log in
118 |
119 |
120 |
121 |
122 |

123 |
124 |
125 | >
126 | )
127 | }
128 |
129 | export default ResetPwd
130 |
--------------------------------------------------------------------------------
/src/components/auth/signup_client.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react";
2 | import "../../styles/signup.sass";
3 | import axios from "axios";
4 | import face from "../../assets/client.png";
5 | import Navbar from "../utilities/Navbar";
6 | import { useNavigate } from "react-router-dom";
7 | import { AiFillEye, AiFillEyeInvisible } from "react-icons/ai";
8 | import { BsFillCloudUploadFill } from "react-icons/bs";
9 | import { Link } from "react-router-dom";
10 | import { toast } from "react-toastify";
11 | import firebase from "firebase/compat/app";
12 | import "firebase/compat/auth";
13 | import "firebase/compat/firestore";
14 | import { storage } from "../../config/fbConfig";
15 | import { ref, getDownloadURL, uploadBytesResumable } from "firebase/storage";
16 |
17 | function SignupClient() {
18 | const [show, setShow] = React.useState(false);
19 | const [show2, setShow2] = React.useState(false);
20 | const [profilePic, setProfilePic] = React.useState(false);
21 | const [img, setImg] = React.useState('')
22 |
23 | const handleClick = () => setShow(!show);
24 | const handleClick2 = () => setShow2(!show2);
25 | let navigate = useNavigate();
26 | const [signupData, setSignupData] = useState({
27 | firstname: "",
28 | lastname: "",
29 | phonenumber: "",
30 | email: "",
31 | password: "",
32 | confirmpassword: "",
33 | image: "",
34 | });
35 |
36 | const uploadFile = async (e) => {
37 | const storageRef = ref(storage, `/files/pic1s/${profilePic.name}`);
38 | const uploadTask = uploadBytesResumable(storageRef, signupData.image);
39 |
40 | uploadTask.on(
41 | "state changed",
42 | (snapshot) => {
43 | let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
44 | console.log(progress);
45 | },
46 | (err) => console.log(err),
47 | () => {
48 | getDownloadURL(uploadTask.snapshot.ref).then((url) => {
49 | setImg(url);
50 | });
51 | }
52 | );
53 | };
54 |
55 | const handleSubmit = (e) => {
56 | uploadFile()
57 | .then((result) => {
58 | e.preventDefault();
59 | var pattern = new RegExp("[0][5-7][0-9]*");
60 |
61 | if (!pattern.test(signupData.phonenumber)) {
62 | toast.error("Your phone number is not valid");
63 | return;
64 | }
65 | if (!img) {
66 | toast.error('Please upload an ID image')
67 | return
68 | }
69 | if (signupData.password === signupData.confirmpassword) {
70 | axios
71 | .post("http://localhost:8000/signup", {
72 | firstname: signupData.firstname,
73 | lastname: signupData.lastname,
74 | phonenumber: signupData.phonenumber,
75 | email: signupData.email,
76 | password: signupData.password,
77 | role: 2,
78 | image: img,
79 | })
80 | .then((response) => {
81 | console.log(response);
82 | if (response.data.user) {
83 | toast.success("Account successfully created");
84 | setTimeout(() => {
85 | navigate("/login");
86 | }, 2500);
87 | setTimeout(() => {
88 | toast.warning(
89 | "An email has been sent to verify your account"
90 | );
91 | }, 4000);
92 | } else {
93 | if (response.data.keyPattern.email === 1) {
94 | toast.error("the email is already used");
95 | }
96 | }
97 | })
98 | .catch((error) => console.log(error));
99 | } else {
100 | toast.error("Password and confirmation do not match");
101 | }
102 | })
103 | .catch((err) => {
104 | console.log(err);
105 | });
106 | };
107 | return (
108 | <>
109 |
110 |
111 |
112 |
Register as Client
113 |
304 |
305 |
306 |
307 | Already have an account? Log in
308 |
309 |
310 |
311 |
312 | Want to be a host? Sign up as host
313 |
314 |
315 |
316 |
317 |

318 |
319 |
320 | >
321 | );
322 | }
323 |
324 | export default SignupClient;
325 |
--------------------------------------------------------------------------------
/src/components/auth/signup_host.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import axios from 'axios'
3 | import '../../styles/signup.sass'
4 | import face from '../../assets/h2.png'
5 | import Navbar from '../utilities/Navbar'
6 | import { AiFillEye, AiFillEyeInvisible } from 'react-icons/ai'
7 | import { BsFillCloudUploadFill } from 'react-icons/bs'
8 | import { Link } from 'react-router-dom'
9 | import { useNavigate } from 'react-router-dom'
10 | import { toast } from 'react-toastify'
11 | import { storage } from '../../config/fbConfig'
12 | import { ref, getDownloadURL, uploadBytesResumable } from 'firebase/storage'
13 |
14 | function SignupHost() {
15 | const [show, setShow] = React.useState(false)
16 | const [show2, setShow2] = React.useState(false)
17 | const [profilePic, setProfilePic] = React.useState(false)
18 | const [img, setImg] = React.useState('')
19 |
20 | const handleClick = () => setShow(!show)
21 | const handleClick2 = () => setShow2(!show2)
22 | let navigate = useNavigate()
23 | const [signupData, setSignupData] = useState({
24 | firstname: '',
25 | lastname: '',
26 | phonenumber: '',
27 | email: '',
28 | password: '',
29 | confirmpassword: '',
30 | image: '',
31 | ville: '',
32 | street: '',
33 | })
34 |
35 |
36 |
37 | const uploadFile = async (e) => {
38 | const storageRef = ref(storage, `/files/pic1s/${profilePic.name}`)
39 | const uploadTask = uploadBytesResumable(storageRef, profilePic)
40 |
41 | uploadTask.on(
42 | 'state changed',
43 | (snapshot) => {
44 | let progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100
45 | console.log(progress)
46 | },
47 | (err) => console.log(err),
48 | () => {
49 | getDownloadURL(uploadTask.snapshot.ref).then((url) => {
50 | setImg(url)
51 | })
52 | }
53 | )
54 | }
55 | const handleSubmit = (e) => {
56 | e.preventDefault()
57 |
58 | uploadFile()
59 | .then((result) => {
60 | e.preventDefault()
61 | var pattern = new RegExp('[0][5-7][0-9]*')
62 | if (!pattern.test(signupData.phonenumber)) {
63 | toast.error('Your phone number is not valid')
64 | return
65 | }
66 | if (!img) {
67 | toast.error('Please upload an ID image')
68 | return
69 | }
70 | if (signupData.password === signupData.confirmpassword) {
71 | axios
72 | .post('http://localhost:8000/signup', {
73 | firstname: signupData.firstname,
74 | lastname: signupData.lastname,
75 | phonenumber: signupData.phonenumber,
76 | email: signupData.email,
77 | password: signupData.password,
78 | role: 3,
79 | image: img,
80 | city: signupData.ville,
81 | street: e.target.street,
82 | })
83 | .then((response) => {
84 | if (response.data.user) {
85 | toast.success('Account successfully created')
86 | setTimeout(() => {
87 | navigate('/login')
88 | }, 2500)
89 | setTimeout(() => {
90 | toast.warning('An email has been sent to verify your account')
91 | }, 4000)
92 | } else {
93 | if (response.data.keyPattern.email === 1) {
94 | toast.error('the email is already used')
95 | }
96 | }
97 | })
98 | .catch((error) => console.log(error))
99 | } else {
100 | toast.error('Password and confirmation do not match')
101 | }
102 | })
103 | .catch((err) => {
104 | console.log(err)
105 | })
106 | }
107 | return (
108 | <>
109 |
110 |
111 |
112 |

113 |
114 |
115 |
Register as Host
116 |
358 |
359 |
360 |
361 | Already have an account? Log in
362 |
363 |
364 |
365 |
366 | >
367 | )
368 | }
369 | export default SignupHost
370 |
--------------------------------------------------------------------------------
/src/components/client/profile.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable react/jsx-no-undef */
2 | /* eslint-disable react-hooks/rules-of-hooks */
3 | import React, { useState, useEffect } from 'react'
4 | import Navbar from '../utilities/Navbar'
5 | import { Container, Row, Col } from 'reactstrap'
6 | import { BsFillCloudUploadFill } from 'react-icons/bs'
7 | import { BsCheck2Circle, BsSnow } from 'react-icons/bs'
8 |
9 | import '../../styles/profile.sass'
10 | import {
11 | Badge,
12 | Button,
13 | Center,
14 | Flex,
15 | Heading,
16 | Image,
17 | Stack,
18 | Text,
19 | useDisclosure,
20 | } from '@chakra-ui/react'
21 |
22 | const profile = () => {
23 | const [searchField, setSearchField] = useState('')
24 | const [user, setUser] = useState('')
25 |
26 | const [image, setImage] = useState('')
27 | const [profilePic, setProfilePic] = useState('')
28 | const [src, setSrc] = useState('')
29 |
30 | const src2 =
31 | 'https://images.unsplash.com/photo-1568605114967-8130f3a36994?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80'
32 | const getUser = () => {
33 | let userSession = JSON.parse(sessionStorage.getItem('USER'))
34 | setUser(userSession.user)
35 | }
36 |
37 | useEffect(() => {
38 | getUser()
39 | }, [])
40 |
41 | const handleChange = (e) => {
42 | setSearchField(e.target.value)
43 | }
44 |
45 | return (
46 |
47 |
48 |
49 |
50 |
51 | hello {user.firstname} , you wanna change your image ?
52 |
53 |
63 | {
69 | setProfilePic(e.target.files[0])
70 | setSrc(URL.createObjectURL(e.target.files[0]))
71 | }}
72 | />
73 |
76 |
77 |

78 |
79 |
80 |
81 | {
82 | /* {loading ? : posts.map((post, i) => (*/
83 |
98 | /* ))} */
99 | }
100 | {
101 | /* {loading ? : posts.map((post, i) => (*/
102 |
117 | /* ))} */
118 | }
119 |
120 |
121 |
122 | Whihlist
123 |
124 |
125 |
126 | )
127 | }
128 |
129 | export default profile
130 |
131 | function AdminPostCard({
132 | imageUrl,
133 | title,
134 | price,
135 | baths,
136 | beds,
137 | rating,
138 | verified,
139 | space,
140 | city,
141 | id,
142 | agents,
143 | feedBack,
144 | }) {
145 | const { isOpen, onOpen, onClose } = useDisclosure()
146 | return (
147 |
148 |
158 |
159 |
160 |
161 |
169 |
170 |
171 | {title}
172 |
173 |
174 | {verified ? (
175 |
183 |
184 |
185 | ) : (
186 | ''
187 | )}
188 |
189 |
190 | {city}
191 |
192 |
193 | {beds} BEDS • {baths} BATHS •{space} M°2
194 |
195 |
196 |
197 | $ {price}/ night
198 |
199 |
200 |
201 |
219 |
220 |
221 |
222 | )
223 | }
224 |
--------------------------------------------------------------------------------
/src/components/host/dashboardCopoments/Slider/BtnSlider.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "../../../../styles/Slider.sass";
3 |
4 | import {AiOutlineArrowRight ,AiOutlineArrowLeft } from "react-icons/ai"
5 | import {BsArrowLeft} from "react-icons/bs"
6 |
7 | export default function BtnSlider({ direction, moveSlide }) {
8 | console.log(direction, moveSlide);
9 | return (
10 |
17 | );
18 | }
--------------------------------------------------------------------------------
/src/components/host/hostHome.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import SidebarWithHeader from "./hostLayout"
3 |
4 | function Home() {
5 | return (
6 |
7 | Home
8 |
9 |
10 | )
11 | }
12 |
13 | export default Home
--------------------------------------------------------------------------------
/src/components/host/hostLayout.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import axios from "axios";
3 | import {
4 | IconButton,
5 | Avatar,
6 | Box,
7 | CloseButton,
8 | Flex,
9 | HStack,
10 | VStack,
11 | Icon,
12 | useColorModeValue,
13 | Link,
14 | Drawer,
15 | DrawerContent,
16 | Text,
17 | useDisclosure,
18 | BoxProps,
19 | FlexProps,
20 | Menu,
21 | MenuButton,
22 | MenuDivider,
23 | MenuItem,
24 | MenuList,
25 | } from "@chakra-ui/react";
26 | import { FiHome, FiMenu, FiChevronDown } from "react-icons/fi";
27 | import {
28 | BsCalendarCheck,
29 | BsBell,
30 | BsPatchCheck,
31 | BsPatchExclamation,
32 | } from "react-icons/bs";
33 | import { BiTimeFive, BiImageAdd } from "react-icons/bi";
34 | import { Link as reactRouter, useNavigate, Navigate } from "react-router-dom";
35 | import { MdPublic } from "react-icons/md";
36 | import { useSelector, useDispatch } from "react-redux";
37 | import { toast } from "react-toastify";
38 | import { actions } from "../../state/auth_slice";
39 | import logo from "../../assets/Rented.png";
40 |
41 | const LinkItems = [
42 | { name: "Home", icon: FiHome, path: "/host" },
43 | { name: "Posts", icon: MdPublic, path: "/host/posts" },
44 | { name: "Add post", icon: BiImageAdd, path: "/host/addpost" },
45 | { name: "Reservations", icon: BsCalendarCheck, path: "/host/reservations" },
46 | ];
47 |
48 | export default function SidebarWithHeader({ children }) {
49 | const { isOpen, onOpen, onClose } = useDisclosure();
50 | const isLogged = useSelector((state) => state.isLogged);
51 | let navigate = useNavigate();
52 | console.log(isLogged);
53 | // useEffect(() => {
54 | // if (!isLogged) {
55 | // navigate("/login");
56 | // }
57 | // });
58 |
59 | return (
60 |
61 | onClose}
63 | display={{ base: "none", md: "block" }}
64 | />
65 |
74 |
75 |
76 |
77 |
78 | {/* mobilenav */}
79 |
80 |
81 | {children}
82 |
83 |
84 | );
85 | }
86 |
87 | const SidebarContent = ({ onClose, ...rest }) => {
88 | return (
89 |
99 |
100 |
101 |

102 |
103 |
104 |
105 |
106 | {LinkItems.map((link) => (
107 |
108 | {link.name}
109 |
110 | ))}
111 |
112 | );
113 | };
114 |
115 | const NavItem = ({ icon, children, path, ...rest }) => {
116 | return (
117 |
123 |
136 | {icon && (
137 |
145 | )}
146 | {children}
147 |
148 |
149 | );
150 | };
151 |
152 | const MobileNav = ({ onOpen, ...rest }) => {
153 | const [notifications, setNotifications] = useState([]);
154 | useEffect(() => {
155 | getNotifications();
156 | }, []);
157 | const getNotifications = () => {
158 | console.log("opened");
159 | axios
160 | .post("http://localhost:8000/getNotificationByidHost", {
161 | id: "6245f759dcaa169f72781127",
162 | })
163 | .then((response) => {
164 | const notifications = response.data.result;
165 | setNotifications(notifications);
166 | console.log(notifications);
167 | })
168 | .catch((err) => {
169 | console.log(err);
170 | });
171 | };
172 | const dispatch = useDispatch();
173 | let userSession = JSON.parse(sessionStorage.getItem("USER"));
174 | if (userSession) {
175 | dispatch(actions.setLogin(true));
176 | } else {
177 | dispatch(actions.setLogin(false));
178 | }
179 |
180 | const logoutHandler = () => {
181 | sessionStorage.removeItem("USER");
182 | dispatch(actions.setLogin(false));
183 | toast.success("Logged out successfully !");
184 | };
185 |
186 | return (
187 |
198 | }
204 | />
205 |
206 |
207 |
208 |

209 |
210 |
211 |
212 |
213 |
253 |
254 |
293 |
294 |
295 |
296 | );
297 | };
298 |
299 | const NotificationItem = ({ notif, iconType }) => {
300 | if (iconType == 1) {
301 | return (
302 |
306 | );
307 | } else if (iconType == 2) {
308 | return (
309 |
313 | );
314 | } else if (iconType == 3) {
315 | return (
316 |
320 | );
321 | } else if (iconType == 4) {
322 | return (
323 |
327 | );
328 | } else
329 | return (
330 |
334 | );
335 | };
336 |
--------------------------------------------------------------------------------
/src/components/host/hostPosts.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import SidebarWithHeader from "./hostLayout";
3 | import {
4 | Badge,
5 | Button,
6 | Center,
7 | Flex,
8 | Heading,
9 | Image,
10 | Stack,
11 | Text,
12 | useDisclosure,
13 | Drawer,
14 | DrawerBody,
15 | Avatar,
16 | DrawerHeader,
17 | DrawerOverlay,
18 | DrawerContent,
19 | DrawerCloseButton,
20 | Box,
21 | Container,
22 | VStack,
23 | SimpleGrid,
24 | StackDivider,
25 | List,
26 | ListItem,
27 | Modal,
28 | ModalOverlay,
29 | ModalContent,
30 | ModalHeader,
31 | ModalFooter,
32 | ModalBody,
33 | ModalCloseButton,
34 | Divider,
35 | } from "@chakra-ui/react";
36 | import { BsCheck2Circle, BsSnow } from "react-icons/bs";
37 | import { FaCouch, FaWifi } from "react-icons/fa";
38 | import { MdKitchen, MdOutlineElectricalServices } from "react-icons/md";
39 | import { BiWater } from "react-icons/bi";
40 | import axios from "axios";
41 | import { toast } from "react-toastify";
42 |
43 | function HostPosts() {
44 | const [posts, setPosts] = useState([]);
45 | const [loading, setLoading] = useState(true);
46 | useEffect(() => {
47 | getPosts();
48 | setLoading(false);
49 | }, []);
50 |
51 | const getPosts = () => {
52 | axios
53 | .post("http://localhost:8001/findPostByIdHost", {
54 | idHost: "624b05de38b856734316b248",
55 | })
56 | .then((response) => {
57 | console.log(response);
58 | const posts = response.data.result;
59 | setPosts(posts);
60 | console.log(posts);
61 | })
62 | .catch((err) => {
63 | console.log(err);
64 | });
65 | };
66 |
67 | // console.log(posts);
68 | return (
69 |
70 | Posts
71 |
72 | {posts.map((post, i) => (
73 |
86 | ))}
87 |
88 |
89 | );
90 | }
91 | function AdminPostCard({
92 | imageUrl,
93 | title,
94 | price,
95 | baths,
96 | beds,
97 | rating,
98 | verified,
99 | space,
100 | city,
101 | id,
102 | }) {
103 | const { isOpen, onOpen, onClose } = useDisclosure();
104 | return (
105 |
106 |
116 |
117 |
118 |
119 |
127 |
128 |
129 | {title}
130 |
131 |
132 | {verified ? (
133 |
141 |
142 |
143 | ) : (
144 | ""
145 | )}
146 |
147 |
148 | {city}
149 |
150 |
151 | {beds} BEDS • {baths} BATHS •{space} M°2
152 |
153 |
154 |
155 | $ {price}/ night
156 |
157 |
158 |
159 |
177 |
191 |
192 |
193 |
194 | );
195 | }
196 |
197 | function DetailsDrawer({
198 | onClose,
199 | isOpen,
200 | imageUrl,
201 | title,
202 | price,
203 | baths,
204 | beds,
205 | rating,
206 | verified,
207 | space,
208 | city,
209 | id,
210 | }) {
211 | return (
212 |
213 |
214 |
215 |
216 |
217 |
218 |
230 |
231 |
232 |
233 | );
234 | }
235 |
236 | function DetailsDrawerData({
237 | imageUrl,
238 | title,
239 | price,
240 | baths,
241 | beds,
242 | rating,
243 | verified,
244 | space,
245 | city,
246 | idPost,
247 | }) {
248 | const { isOpen, onOpen, onClose } = useDisclosure();
249 | const {
250 | isOpen: isConfirmOpen,
251 | onOpen: onConfirmOpen,
252 | onClose: onConfirmClose,
253 | } = useDisclosure();
254 | const {
255 | isOpen: isDeleteOpen,
256 | onOpen: onDeleteOpen,
257 | onClose: onDeleteClose,
258 | } = useDisclosure();
259 | const {
260 | isOpen: isFeedOpen,
261 | onOpen: onFeedOpen,
262 | onClose: onFeedClose,
263 | } = useDisclosure();
264 |
265 | const ConfirmPostHandler = (id) => {
266 | axios
267 | .patch("http://localhost:8001/UpdatePostStatus", {
268 | id: id,
269 | })
270 | .then(function (response) {
271 | console.log(response);
272 | onConfirmClose();
273 | toast.success("This post is now verified !");
274 | setTimeout(() => {
275 | window.location.reload(false);
276 | }, 3000);
277 | })
278 | .catch(function (error) {
279 | console.log(error);
280 | });
281 | };
282 |
283 | return (
284 |
285 |
290 |
291 |
300 |
301 |
302 |
303 |
308 | {title}
309 |
310 |
311 | ${price} /NIGHT
312 |
313 |
314 |
315 | }
319 | >
320 |
321 |
322 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed
323 | diam nonumy eirmod tempor invidunt ut labore
324 |
325 |
326 |
327 |
334 | Features
335 |
336 |
337 |
338 |
339 |
340 | Water
341 |
342 |
343 | Gas {" "}
344 |
345 |
346 |
347 | Electricity {" "}
348 |
349 |
350 |
351 |
352 | {" "}
353 | Furniture
354 |
355 |
356 | Wifi {" "}
357 |
358 |
359 | Air conditioning
360 |
361 |
362 |
363 |
364 |
365 |
372 | Post Details
373 |
374 |
375 |
376 |
377 |
378 | Local type:
379 | {" "}
380 | Villa
381 |
382 |
383 |
384 | City:
385 | {" "}
386 | {city}
387 |
388 |
389 |
390 | Street:
391 | {" "}
392 | Oran
393 |
394 |
395 |
396 | Number of beds:
397 | {" "}
398 | {beds}
399 |
400 |
401 |
402 | Number of baths:
403 | {" "}
404 | {baths}
405 |
406 |
407 |
408 | Space:
409 | {" "}
410 | {space} M°2
411 |
412 |
413 |
414 | Rating:
415 | {" "}
416 | {rating}
417 |
418 |
419 |
420 |
421 | Verification:
422 | {" "}
423 |
424 | {verified ? (
425 |
433 | Verified
434 |
435 | ) : (
436 |
437 |
440 |
441 |
446 |
447 |
448 | Agents
449 |
450 |
451 | {Array(5)
452 | .fill("")
453 | .map((_, i) => (
454 |
455 | ))}
456 |
457 |
458 |
459 |
460 | )}
461 |
462 |
463 |
464 |
465 |
466 | {verified ? (
467 | ""
468 | ) : (
469 |
470 |
480 |
481 |
482 |
483 | Agent's feedback
484 |
485 |
486 | This house is very well organised , everything is
487 | authentic just like in the host's post
488 |
489 |
490 |
491 |
494 |
495 |
496 |
497 |
498 |
514 |
515 |
516 |
517 |
518 |
519 |
520 | Are you sue you want to confirm this post?
521 |
522 |
523 |
524 |
527 |
534 |
535 |
536 |
537 |
538 | )}
539 |
557 |
558 |
559 |
560 |
561 |
562 |
563 | Are you sue you want to Delete this post?
564 |
565 |
566 |
567 |
570 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 | );
581 | }
582 |
583 | function AgentsCard() {
584 | const { isOpen, onOpen, onClose } = useDisclosure();
585 | return (
586 | <>
587 |
593 |
594 |
595 |
596 |
Merzouk ilyes reda
597 |
Oran
598 |
599 |
600 |
604 |
605 |
606 |
607 | Are you sure ?
608 |
609 |
610 |
611 |
614 |
617 |
618 |
619 |
620 |
621 |
622 | >
623 | );
624 | }
625 |
626 | export default HostPosts;
627 |
--------------------------------------------------------------------------------
/src/components/host/reservations.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import SidebarWithHeader from "./hostLayout";
3 | import {
4 | Menu,
5 | MenuButton,
6 | MenuList,
7 | MenuItem,
8 | IconButton,
9 | Avatar,
10 | Button,
11 | Modal,
12 | ModalOverlay,
13 | ModalContent,
14 | ModalHeader,
15 | ModalFooter,
16 | ModalBody,
17 | ModalCloseButton,
18 | useDisclosure,
19 | } from "@chakra-ui/react";
20 | import { BsThreeDotsVertical } from "react-icons/bs";
21 | import { AiOutlineDelete, AiOutlineThunderbolt } from "react-icons/ai";
22 | import { BiDetail } from "react-icons/bi";
23 | function Reservations() {
24 | return (
25 |
26 |
27 |
28 |
Reservations
29 |
30 |
31 |
32 |
33 |
34 |
35 | Client
36 | |
37 |
38 | Amount
39 | |
40 |
41 | Start date
42 | |
43 |
44 | End date
45 | |
46 |
47 | Status
48 | |
49 | |
50 |
51 |
52 |
53 |
60 |
67 |
74 |
81 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | );
96 | }
97 |
98 | export default Reservations;
99 |
100 | const TableItem = ({ clientName, amount, startDate, endDate, status }) => {
101 | return (
102 |
103 |
104 |
112 | |
113 |
114 | ${amount}
115 | |
116 |
117 | {startDate}
118 | Due in 3 days
119 | |
120 |
121 | {endDate}
122 | Due in 7 days
123 | |
124 |
125 |
126 | |
127 |
128 |
142 | |
143 |
144 | );
145 | };
146 | const DetailsMenuItem = () => {
147 | const { isOpen, onOpen, onClose } = useDisclosure();
148 |
149 | return(
150 | } fontSize={18}>
151 | Details
152 |
153 |
154 |
155 | Delete
156 |
157 |
158 |
159 |
160 |
168 |
169 |
170 |
171 |
172 |
173 |
174 | )
175 | }
176 | const TakeActionmenuItem = () => {
177 | const { isOpen, onOpen, onClose } = useDisclosure();
178 |
179 | return (
180 | }
183 | fontSize={18}
184 | >
185 | Take action
186 |
187 |
188 |
189 | Reservation request
190 |
191 | Would you like to accept this reservation request?
192 |
193 |
194 |
202 |
205 |
206 |
207 |
208 |
209 | );
210 | };
211 | const DeleteMenuItem = () => {
212 | const { isOpen, onOpen, onClose } = useDisclosure();
213 |
214 | return (
215 | }
218 | fontSize={18}
219 | >
220 | Delete
221 |
222 |
223 |
224 | Delete
225 |
226 | Are you sure you want to delete this?
227 |
228 |
229 |
237 |
240 |
241 |
242 |
243 |
244 | );
245 | };
246 |
247 | const Status = ({ status }) => {
248 | var bgColor;
249 | var color;
250 | if (status.toLowerCase().includes("acc")) {
251 | bgColor = "bg-green-200";
252 | color = "text-green-900";
253 | } else if (status.toLowerCase().includes("ref")) {
254 | bgColor = "bg-red-200";
255 | color = "text-red-900";
256 | } else if (status.toLowerCase().includes("on")) {
257 | bgColor = "bg-blue-200";
258 | color = "text-blue-900";
259 | } else if (status.toLowerCase().includes("pen")) {
260 | bgColor = "bg-orange-200";
261 | color = "text-orange-900";
262 | } else if (status.toLowerCase().includes("en")) {
263 | bgColor = "bg-gray-200";
264 | color = "text-gray-900";
265 | }
266 | return (
267 |
270 |
274 | {status}
275 |
276 | );
277 | };
278 |
--------------------------------------------------------------------------------
/src/components/products/details.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react'
2 | import Navbar from '../utilities/Navbar'
3 | import '../../styles/details.sass'
4 | import 'react-date-range/dist/styles.css' // main style file
5 | import 'react-date-range/dist/theme/default.css' // theme css file
6 | // import { StarIcon, CheckCircleIcon } from '@chakra-ui/icons'
7 | import {
8 | Modal,
9 | ModalOverlay,
10 | ModalContent,
11 | ModalHeader,
12 | ModalFooter,
13 | useDisclosure,
14 | ModalBody,
15 | ModalCloseButton,
16 | } from '@chakra-ui/react'
17 | import { parseISO } from 'date-fns'
18 |
19 | import { FaCopy, FaBed, FaGasPump, FaWater, FaHeart } from 'react-icons/fa'
20 | import { AiOutlineHeart, AiFillStar, AiFillCheckCircle } from 'react-icons/ai'
21 | import { GiElectric } from 'react-icons/gi'
22 | import axios from 'axios'
23 | import { DateRangePicker } from 'react-date-range'
24 | import * as moment from 'moment'
25 | import { Link, useNavigate } from 'react-router-dom'
26 |
27 | import { toast } from 'react-toastify'
28 |
29 | import {
30 | Container,
31 | Row,
32 | Col,
33 | Form,
34 | Card,
35 | Input,
36 | Button,
37 | Label,
38 | FormGroup,
39 | } from 'reactstrap'
40 |
41 | function Detail() {
42 | const [searchField, setSearchField] = useState('')
43 | const url = 'http://localhost:8001/findPostById'
44 | let navigate = useNavigate()
45 |
46 | const [post, setPost] = useState({})
47 | const [globalRating, setGlobalRating] = useState(0)
48 | const [comments, setComments] = useState([])
49 | const [loadingP, setLoadingP] = useState(true)
50 | const [likedd, setLikedd] = useState(false)
51 |
52 | const [reservationDate, setReservationDate] = useState({
53 | dateDepart: '',
54 | dateDarive: '',
55 | })
56 |
57 | const [reservationPrice, setReservationPrice] = useState(true)
58 |
59 | //for calendar seting
60 | const [selectionRange, setSelectionRange] = useState([])
61 |
62 | const { isOpen, onOpen, onClose } = useDisclosure()
63 |
64 | const imgUrl =
65 | 'https://cloudfront-us-east-1.images.arcpublishing.com/gray/XVMKBJ7L7JAPVCWE2KGHIYBQ3I.jpg'
66 |
67 | const handleChange = (e) => {
68 | setSearchField(e.target.value)
69 | }
70 |
71 | const sumRating = (table) => {
72 | var a = 0
73 | table.map((x) => (a = a + x.ratingValue))
74 |
75 | return a / table.length
76 | }
77 |
78 | useEffect(() => {
79 | getPost()
80 | getDates()
81 | isLiked()
82 | }, [likedd])
83 |
84 | const getPost = () => {
85 | const queryParams = new URLSearchParams(window.location.search)
86 | const id = queryParams.get('id')
87 | axios
88 | .get(`${url}/${id}`)
89 | .then((response) => {
90 | const post = response.data
91 | setPost(post.result)
92 | setLoadingP(false)
93 | setGlobalRating(sumRating(response.data.result.rating))
94 | setComments(post.result.comment)
95 | console.log(post)
96 | })
97 | .catch((err) => {
98 | console.log(err)
99 | })
100 | }
101 |
102 | const isLiked = async () => {
103 | const queryParams = new URLSearchParams(window.location.search)
104 | const id = queryParams.get('id')
105 | let userSession = JSON.parse(sessionStorage.getItem('USER'))
106 | let id_user = userSession.user._id
107 | axios
108 | .post('http://localhost:8000/userById', {
109 | id: id_user,
110 | })
111 | .then((response) => {
112 | console.log(response.data.favourit)
113 | response.data.favourit.map((idp) => {
114 | if (post._id == idp.postId) {
115 | setLikedd(true)
116 | console.log(likedd)
117 | }
118 | })
119 | })
120 | .catch((err) => {
121 | console.log(err)
122 | })
123 | }
124 |
125 | const validDate = (st, en, tab) => {
126 | let cnt = 0
127 | if (en === '' || st === '' || en < st) {
128 | return false
129 | }
130 |
131 | for (let i = 0; i < tab.length; i++) {
132 | if (st > tab[i].endDate || en < tab[i].startDate) {
133 | cnt++
134 | }
135 | }
136 | if (cnt === tab.length) {
137 | return true
138 | } else {
139 | return false
140 | }
141 | }
142 |
143 | const getDates = () => {
144 | const queryParams = new URLSearchParams(window.location.search)
145 | const id = queryParams.get('id')
146 | axios
147 | .get(`http://localhost:8002/PostHasReservations?idpost=${id}`)
148 | .then((response) => {
149 | const tab = []
150 | // eslint-disable-next-line array-callback-return
151 | response.data.result.map((x) => {
152 | tab.push({
153 | startDate: parseISO(`${x.startDate}`),
154 | endDate: parseISO(`${x.endDate}`),
155 | key: 'selection',
156 | })
157 | })
158 |
159 | setSelectionRange(tab)
160 | })
161 | .catch((err) => {
162 | console.log(err)
163 | })
164 | }
165 |
166 | const liking = (e) => {
167 | let postId = post._id
168 | let userSession = JSON.parse(sessionStorage.getItem('USER'))
169 | let userId = userSession.user._id
170 | setLikedd(!likedd)
171 |
172 | axios
173 | .post('http://localhost:8001/liked', {
174 | postId: postId,
175 | userId: userId,
176 | })
177 | .then((result) => {
178 | toast.success('you have liked this post')
179 | })
180 | .catch((err) => {
181 | console.log(err)
182 | })
183 | }
184 |
185 | const makeReservation = (e) => {
186 | e.preventDefault()
187 | const st = new Date(reservationDate.dateDepart)
188 | const en = new Date(reservationDate.dateDarive)
189 | let userSession = JSON.parse(sessionStorage.getItem('USER'))
190 |
191 | if (!validDate(st, en, selectionRange)) {
192 | toast.error('remake your reservation date')
193 | return false
194 | }
195 | axios
196 | .post('http://localhost:8002/addreservation', {
197 | startDate: st,
198 | endDate: en,
199 | id_post: post._id,
200 | id_user: userSession.user._id,
201 | nom_user: `${userSession.user.firstname} ${userSession.user.lastname}`,
202 | id_host: post.idUser,
203 | amount: reservationPrice * post.PricePerNight,
204 | })
205 | .then((response) => {
206 | toast.success('reservation made')
207 | })
208 | .then(
209 | setTimeout(() => {
210 | navigate('/')
211 | }, 2000)
212 | )
213 |
214 | .catch((error) => toast.error('check your internet conection'))
215 | }
216 |
217 | return (
218 | <>
219 |
220 |
221 |
222 |
{loadingP ? 'title' : post.title}
223 |
224 |
225 |
226 | {loadingP ? '' : isNaN(globalRating) ? 'rating' : globalRating}
227 |
237 | {loadingP ? '' : comments.length} comments
238 |
239 |
240 | Verified
241 |
248 | {loadingP ? '' : post.city + ' ' + post.street}
249 |
250 |
251 |
252 |
253 |
261 | Copy
262 |
263 | {likedd ? (
264 | <>
265 |
273 |
281 | like
282 |
283 | >
284 | ) : (
285 | <>
286 |
294 |
302 | like
303 |
304 | >
305 | )}
306 |
307 |
308 |
309 |
310 |

311 |
312 | x{' '}
313 |
314 |

324 |

334 |
335 |
336 |

346 |

356 |
357 |
358 |
359 |
360 |
361 |
362 | {/* {post.nameUser}
*/}
363 |
364 |
365 | {`${post.nbrBeds} Bed et ${post.nbrBathes} Shower , ${post.space} square metres `}
366 |
367 |
368 |
373 |
374 | Description
375 |
376 | {loadingP ? '' : post.description}
377 |
378 |
379 | What you'll find in this appartement
380 |
381 |
382 |
383 | Furnish
384 |
385 |
386 | Gas
387 |
388 |
389 |
390 |
391 | water
392 |
393 |
394 | electricity
395 |
396 |
397 |
398 |
399 |
400 |
407 | // setSelectionRange(...selectionRange, ...item)
408 | console.log('it changed')
409 | }
410 | />
411 |
412 |
413 |
414 |
415 |
425 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 | {' '}
547 |
548 |
549 | {loadingP ? '' : globalRating}
550 |
561 | {loadingP ? '' : comments.length} comments
562 |
563 |
564 |
565 |
566 |
567 | {loadingP
568 | ? ''
569 | : comments.length === 0
570 | ? 'there is no commnt'
571 | : 'there are cmnts'}
572 |
573 |
574 |
575 |
583 |
584 |
585 |
586 | >
587 | )
588 | }
589 |
590 | export default Detail
591 |
--------------------------------------------------------------------------------
/src/components/products/search.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react'
2 | import Navbar from '../utilities/Navbar'
3 | import {
4 | Tabs,
5 | TabList,
6 | TabPanels,
7 | Tab,
8 | TabPanel,
9 | Box,
10 | Badge,
11 | } from '@chakra-ui/react'
12 | import '../../styles/search.sass'
13 | import { GiTreehouse } from 'react-icons/gi'
14 | import { AiFillStar } from 'react-icons/ai'
15 | import {
16 | MdOutlineCabin,
17 | MdOutlineHouseboat,
18 | MdPool,
19 | MdOutlineHouse,
20 | } from 'react-icons/md'
21 | import { GiSpookyHouse } from 'react-icons/gi'
22 | import { BsCheck2Circle, BsHeart, BsHeartFill } from 'react-icons/bs'
23 | import axios from 'axios'
24 | import Skeleton from 'react-loading-skeleton'
25 | import 'react-loading-skeleton/dist/skeleton.css'
26 | import { Link } from 'react-router-dom'
27 |
28 | function Search() {
29 | const [posts, setPosts] = useState([])
30 | const [loading, setLoading] = useState(true)
31 | const [searchField, setSearchField] = useState('')
32 | const url = 'http://localhost:8001/findAllPosts'
33 |
34 | useEffect(() => {
35 | getPosts()
36 | }, [])
37 |
38 | const getPosts = () => {
39 | axios
40 | .get(url)
41 | .then((response) => {
42 | const posts = response.data.result
43 | setPosts(posts)
44 | setLoading(false)
45 | console.log('posts =>' + posts)
46 | })
47 | .catch((err) => {
48 | console.log(err)
49 | })
50 | }
51 |
52 | const filteredPosts = posts.filter((post) => {
53 | return (
54 | post.title.toLowerCase().includes(searchField.toLowerCase()) ||
55 | post.city.toLowerCase().includes(searchField.toLowerCase())
56 | )
57 | })
58 |
59 | const handleChange = (e) => {
60 | setSearchField(e.target.value)
61 | console.log(searchField)
62 | }
63 |
64 | return (
65 | <>
66 |
67 |
68 |
69 |
70 |
71 | {' '}
72 | Farms{' '}
73 |
74 |
75 | {' '}
76 | Apartement
77 |
78 |
79 | {' '}
80 | Beach front
81 |
82 |
83 | {' '}
84 |
85 | Amazing pools
86 |
87 |
88 | {' '}
89 | Villa
90 |
91 |
92 |
93 |
94 |
95 | {loading
96 | ? Array(8)
97 | .fill('')
98 | .map((_, i) =>
)
99 | : filteredPosts
100 | .filter((post) => post.type === 1 && post.verified)
101 | .map((post, i) => (
102 |
117 | ))}
118 |
119 |
120 |
121 |
122 | {loading
123 | ? Array(8)
124 | .fill('')
125 | .map((_, i) =>
)
126 | : filteredPosts
127 | .filter((post) => post.type === 2 && post.verified)
128 | .map((post, i) => (
129 |
142 | ))}
143 |
144 |
145 |
146 |
147 | {loading
148 | ? Array(8)
149 | .fill('')
150 | .map((_, i) =>
)
151 | : filteredPosts
152 | .filter((post) => post.type === 3 && post.verified)
153 | .map((post, i) => (
154 |
167 | ))}
168 |
169 |
170 |
171 |
172 | {loading
173 | ? Array(8)
174 | .fill('')
175 | .map((_, i) =>
)
176 | : filteredPosts
177 | .filter((post) => post.type === 4 && post.verified)
178 | .map((post, i) => (
179 |
192 | ))}
193 |
194 |
195 |
196 |
197 | {loading
198 | ? Array(8)
199 | .fill('')
200 | .map((_, i) =>
)
201 | : filteredPosts
202 | .filter((post) => post.type === 5 && post.verified)
203 | .map((post, i) => (
204 |
217 | ))}
218 |
219 |
220 |
221 |
222 |
223 | >
224 | )
225 | }
226 |
227 | export default Search
228 |
229 | export const PostCard = ({
230 | postId,
231 | imageUrl,
232 | title,
233 | beds,
234 | baths,
235 | rating,
236 | reviewCount,
237 | price,
238 | verified,
239 | space,
240 | city,
241 | }) => {
242 | const property = {
243 | imageAlt: 'Rear view of modern home with pool',
244 | beds: 3,
245 | baths: 2,
246 | title: 'Modern home in city center',
247 | formattedPrice: '1.900',
248 | reviewCount: 34,
249 | rating: 4,
250 | }
251 |
252 | return (
253 |
254 |
261 |
262 |
263 | {/*
264 |
265 |
*/}
266 |
267 |
268 |
269 |
270 |
271 |
272 |
280 | {beds} beds • {baths} baths • {space} m°2
281 |
282 | {verified ? (
283 |
290 | Verified
291 |
292 | ) : (
293 | ''
294 | )}
295 |
296 |
297 |
304 | {title} - {city}
305 |
306 |
307 |
308 | $ {price}
309 |
310 | / night
311 |
312 |
313 |
314 |
315 | {Array(5)
316 | .fill('')
317 | .map((_, i) => (
318 |
319 | ))}
320 | {/* {rating} */}
321 | {/*
322 | {property.reviewCount} reviews
323 | */}
324 |
325 |
326 |
327 |
328 | )
329 | }
330 |
331 | const SkeltonPostCard = () => {
332 | return (
333 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 | )
360 | }
361 |
--------------------------------------------------------------------------------
/src/components/utilities/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import "../../styles/navbar.sass";
3 | import { FaSearchLocation } from "react-icons/fa";
4 | import { Show } from "@chakra-ui/react";
5 | import { GoThreeBars } from "react-icons/go";
6 | import {
7 | Drawer,
8 | DrawerBody,
9 | DrawerHeader,
10 | DrawerOverlay,
11 | DrawerContent,
12 | useDisclosure,
13 | Menu,
14 | MenuButton,
15 | MenuItem,
16 | MenuList,
17 | Box,
18 | Avatar,
19 | } from "@chakra-ui/react";
20 | import { Link } from "react-router-dom";
21 | import { useSelector, useDispatch } from "react-redux";
22 | import { toast } from "react-toastify";
23 | import { actions } from "../../state/auth_slice";
24 | import logo from "../../assets/Rented.png"
25 | function Navbar({ searchInput }) {
26 | const { isOpen, onOpen, onClose } = useDisclosure();
27 | const dispatch = useDispatch();
28 | let userSession = JSON.parse(sessionStorage.getItem("USER"));
29 | if (userSession) {
30 | dispatch(actions.setLogin(true));
31 | } else {
32 | dispatch(actions.setLogin(false));
33 | }
34 | const isLogged = useSelector((state) => state.isLogged);
35 | const logoutHandler = () => {
36 | sessionStorage.removeItem("USER");
37 | dispatch(actions.setLogin(false));
38 | toast.success("Logged out successfully !");
39 | };
40 |
41 | return (
42 |
43 |
44 |

45 |
46 |
47 |
48 |
49 | {" "}
50 |
Home
51 |
52 |
53 | {" "}
54 |
Locals
55 |
56 |
57 | {" "}
58 |
About
59 |
60 |
61 |
71 | {!isLogged ? (
72 |
73 |
74 |
75 |
76 |
77 | ) : (
78 |
91 | )}
92 |
93 |
94 |
95 |
96 |
97 |
98 | Logo
99 |
100 |
101 |
102 | {" "}
103 |
Home
104 |
105 |
106 | {" "}
107 |
Locals
{" "}
108 |
109 |
110 | {" "}
111 |
About
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | );
126 | }
127 |
128 | export default Navbar;
129 |
--------------------------------------------------------------------------------
/src/config/fbConfig.js:
--------------------------------------------------------------------------------
1 | // Import the functions you need from the SDKs you need
2 | import { initializeApp } from 'firebase/app'
3 | import { getStorage } from 'firebase/storage'
4 |
5 | // TODO: Add SDKs for Firebase products that you want to use
6 | // https://firebase.google.com/docs/web/setup#available-libraries
7 |
8 | // Your web app's Firebase configuration
9 | // For Firebase JS SDK v7.20.0 and later, measurementId is optional
10 | const firebaseConfig = {
11 | apiKey: 'AIzaSyCUF2JlCnV6AxhAxo5wTJbKQfP741-qPdQ',
12 | authDomain: 'cpiproject-7761a.firebaseapp.com',
13 | projectId: 'cpiproject-7761a',
14 | storageBucket: 'cpiproject-7761a.appspot.com',
15 | messagingSenderId: '820229834176',
16 | appId: '1:820229834176:web:ffb75cf1e5948af29a3425',
17 | measurementId: 'G-S7P09QE5N6',
18 | }
19 |
20 | // Initialize Firebase
21 | const app = initializeApp(firebaseConfig)
22 | const storage = getStorage(app)
23 |
24 | export { storage, app }
25 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import { BrowserRouter, Routes, Route } from 'react-router-dom'
4 | import Admin from './components/admin/adminHome'
5 |
6 | import Agent from './components/agent/agentHome'
7 | import Host from './components/host/hostHome'
8 | import Login from './components/auth/login'
9 | import SignupHost from './components/auth/signup_host'
10 | import SignupClient from './components/auth/signup_client'
11 | import { ChakraProvider } from '@chakra-ui/react'
12 | import { ToastContainer } from 'react-toastify'
13 | import 'react-toastify/dist/ReactToastify.css'
14 | import ResetPwd from './components/auth/reset'
15 | import { store } from './state/store'
16 | import { Provider } from 'react-redux'
17 | import Search from './components/products/search'
18 | import Details from './components/products/details'
19 | import About from './components/about'
20 | import ForgetPassword from './components/auth/forget'
21 | import AgentHome from './components/agent/agentHome'
22 | import 'react-toastify/dist/ReactToastify.css'
23 |
24 | import Home from './components/host/hostHome'
25 | import Reservations from './components/host/reservations'
26 |
27 | import Posts from './components/host/dashboardCopoments/Posts'
28 | import HostPosts from './components/host/hostPosts'
29 | import './App.sass'
30 | import AdminPosts from './components/admin/adminPosts'
31 | import AdminUsers from './components/admin/adminUsers'
32 | import Profile from './components/client/profile'
33 |
34 | ReactDOM.render(
35 |
36 |
37 |
48 |
49 |
50 | {/* } /> */}
51 | } />
52 | } />
53 | } />
54 |
55 | } />
56 | } />
57 | } />
58 | } />
59 | } />
60 |
61 | } />
62 | } />
63 | } />
64 |
65 |
66 |
67 | } />
68 | } />
69 | } />
70 | } />
71 |
72 |
73 |
74 | } />
75 |
76 |
77 | } />
78 |
79 |
80 |
84 | 404 | NOT FOUND
85 |
86 | }
87 | />
88 |
89 |
90 |
91 | ,
92 | document.getElementById('root')
93 | )
94 |
95 | // If you want to start measuring performance in your app, pass a function
96 | // to log results (for example: reportWebVitals(console.log))
97 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
98 |
--------------------------------------------------------------------------------
/src/state/auth_slice.js:
--------------------------------------------------------------------------------
1 | import { createSlice} from '@reduxjs/toolkit'
2 |
3 | export const authSlice = createSlice({
4 | name: 'isLogged',
5 | initialState: { isLogged: false },
6 | reducers: {
7 | setLogin(state, action) {
8 | state.isLogged = action.payload;
9 | },
10 |
11 | },
12 | })
13 |
14 | export const actions = authSlice.actions;
15 | export default authSlice.reducer
--------------------------------------------------------------------------------
/src/state/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit'
2 | import authReducer from "./auth_slice"
3 |
4 | export const store = configureStore({
5 | reducer: authReducer
6 | })
--------------------------------------------------------------------------------
/src/styles/Admin.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 | .dashbord
4 | height: 100vh
5 | display: grid
6 | grid-template-columns: 10rem auto 15rem
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/styles/Slider.sass:
--------------------------------------------------------------------------------
1 | .container-slider
2 |
3 | height: 300px
4 | margin: 50px 20px auto 20px
5 | position: relative
6 | overflow: hidden
7 | box-shadow: 0 10px 20px #FF5A5F40
8 |
9 |
10 |
11 | .slide
12 | width: 100%
13 | height: 100%
14 | opacity: 0
15 | transition: opacity ease-in-out 0.4s
16 |
17 | .slide img
18 | width: 100%
19 | height: 100%
20 | object-fit: cover
21 |
22 | .active-anim
23 | opacity: 1
24 |
25 |
26 | .btn-slide
27 | width: 60px
28 | height: 60px
29 | border-radius: 50%
30 | background: #FF5A5F20
31 | border: 1px solid #FF5A5F
32 | display: flex
33 | cursor: pointer
34 |
35 |
36 | .btn-slide img
37 | width: 25px
38 | height: 25px
39 | pointer-events: none
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .container-dots
48 |
49 | bottom: 20px
50 | left: 50%
51 | transform: translateX(-50%)
52 | display: flex
53 |
54 | .dot
55 | width: 20px
56 | height: 20px
57 | border-radius: 50%
58 | border: 3px solid #FF5A5F20
59 | margin: 0 5px
60 | background: #FFFFFF
61 |
62 | .dot.active
63 | background: #FF5A5F
64 |
--------------------------------------------------------------------------------
/src/styles/_variables.sass:
--------------------------------------------------------------------------------
1 | $primary-color: #FF5A5F
2 |
--------------------------------------------------------------------------------
/src/styles/dashboardCompoments/Dashboard.sass:
--------------------------------------------------------------------------------
1 | .posts
2 | margin-top: 20px
3 | margin-left : 20px
4 | display: grid
5 | grid-template-columns: repeat(2,1fr)
6 | gap: 20px
7 |
--------------------------------------------------------------------------------
/src/styles/dashboardCompoments/Posts.sass:
--------------------------------------------------------------------------------
1 | @import ".././_variables"
2 |
3 | .addpost
4 | height: 100vh
5 | display: grid
6 | grid-template-columns: 50% 50%
7 | @media screen and (max-width:900px)
8 | grid-template-columns: 100%
9 | .title
10 | font-size: 2.5em
11 | letter-spacing: 1px
12 | margin : 2rem 0rem 0rem 2rem
13 |
14 | .form
15 | margin : 20px
16 | input
17 | padding: 20px
18 |
19 |
20 |
21 |
22 | .group
23 | display: flex
24 | justify-content: space-between
25 | input
26 | margin-top: 10px
27 | width: 200px
28 | height: 45px
29 | border-radius: 5px
30 | border: 1px solid #00000026
31 | padding: 20px
32 | &:focus
33 | border: 1px solid $primary-color
34 | outline: none
35 | input
36 | margin-top: 10px
37 | width: 200px
38 | height: 45px
39 | border-radius: 5px
40 | border: 1px solid #00000026
41 | padding: 20px
42 | &:focus
43 | border: 1px solid $primary-color
44 | outline: none
45 |
46 |
47 |
48 | .titre
49 | width: 100%
50 |
51 |
52 | input[type="file"]
53 | display: none
54 |
55 | .description
56 | textarea
57 | width: 100%
58 | height: 100px
59 | border-radius: 5px
60 | border: 1px solid #00000026
61 | padding: 20px
62 | margin-top : 10px
63 | &:focus
64 | border: 1px solid $primary-color
65 | outline: none
66 |
67 | .cb
68 | display : flex
69 | margin : 1rem
70 | gap : 0rem
71 | .bt
72 | width: 100%
73 | height: 45px
74 | border: none
75 | border-radius: 5px
76 | background-color: $primary-color !important
77 | color: #ffffff
78 | margin-top: 1.5em
79 | cursor: pointer
80 | letter-spacing: 1px
81 | display: flex
82 | align-items: center
83 | justify-content: center
84 |
85 |
86 |
87 | .upload-file
88 | height: 50px
89 | width: 93%
90 | margin: 50px 20px auto 20px
91 | background-color: #fff
92 | border: 1px solid $primary-color
93 | border-radius: 5px
94 | color: $primary-color
95 | display: flex
96 | justify-content: center
97 | align-items: center
98 | font-size: 1.2em
99 |
100 | .chekboxes
101 | margin-top : 20px
102 | .container-slider
103 |
104 |
105 | overflow: hidden
106 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2)
107 |
108 | @media screen and (max-width: 700px)
109 | .container-slider
110 | margin: 100px 10px 0
111 |
112 | .slider
113 | display : flex
114 | flex-direction: column;
115 |
116 | .slide
117 | width: 100%
118 | height: 93%
119 | position: absolute
120 | opacity: 0
121 | transition: opacity ease-in-out 0.4s
122 |
123 | .slide img
124 | width: 100%
125 | height: 100%
126 | object-fit: cover
127 |
128 | .active-anim
129 | opacity: 1
130 |
131 |
132 | .btn-slide
133 |
134 | width: 60px
135 | height: 60px
136 | border-radius: 50%
137 | background: #f1f1f1
138 | border: 1px solid rgba(34, 34, 34, 0.287)
139 | position: absolute
140 | display: flex
141 | justify-content: center
142 | align-items: center
143 | cursor: pointer
144 |
145 |
146 | .btn-slide img
147 | width: 25px
148 | height: 25px
149 | pointer-events: none
150 |
151 |
152 |
153 | .prev
154 |
155 | top : 40%
156 | margin-left : 20px
157 |
158 |
159 | .next
160 |
161 | top : 40%
162 | right : 20px
163 |
164 |
165 |
166 | .container-dots
167 | position: absolute
168 |
169 |
170 | transform: translateX(-50%);
171 | display: flex;
172 |
173 |
174 | .dot
175 | width: 20px
176 | height: 20px
177 | border-radius: 50%
178 | border: 3px solid #f1f1f1
179 | margin: 0 5px
180 | background: #f1f1f1
181 |
182 | .dot.active
183 | background: rgb(32, 32, 32)
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/src/styles/details.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 |
4 | #first-breaker
5 | margin: 20px 0
6 |
7 | .colDv
8 | display: flex
9 | margin-bottom: 16px
10 | .iconEquip
11 | font-size: 25px !important
12 | margin-right: 15px !important
13 |
14 | .userImg
15 | width: 60px
16 | height: 60px
17 | float: right
18 | margin-top: -50px
19 | border-radius: 50%
20 | .container
21 | margin: 30px 100px
22 | .title
23 | font-size: 1.5rem
24 | font-weight: 600
25 | margin-bottom: 12px
26 | margin-left: auto
27 | .subtitles
28 | display: flex
29 | p
30 | font-size: .9rem
31 | display: flex
32 | .icon
33 | color: $primary-color
34 | margin-right: 8px
35 | .icon2
36 | color: $primary-color
37 | margin-right: 6px
38 | margin-left: 8px
39 |
40 | .pics
41 | display: flex
42 | margin-top: 25px
43 | div:nth-child(3)
44 | border-top-right-radius: 8px
45 | border-bottom-right-radius: 8px
46 | div
47 | flex: 1
48 | margin-left: 8px
49 | height: 382px
50 | overflow: hidden
51 | img:first-child
52 | margin-bottom: 1%
53 | img:nth-child(2)
54 | // height: 181px
55 | // width: 308px
56 | .first
57 | flex: 2
58 | border-top-left-radius: 8px
59 | border-bottom-left-radius: 8px
60 | margin-left: 0px
61 | img
62 | margin-bottom: 0px !important
63 |
64 |
65 | .rdrInRange
66 | background-color: $primary-color !important
67 |
68 | .rdrEndEdge
69 | background-color: $primary-color !important
70 | right: 3px
71 | border-top-right-radius: 13px !important
72 | border-bottom-right-radius: 13px !important
73 |
74 | .rdrStartEdge
75 | background-color: $primary-color !important
76 | border-top-left-radius: 13px !important
77 | border-bottom-left-radius: 13px !important
78 | left: 3px
79 |
80 | .rdrDayInPreview
81 | border-top: 1px solid $primary-color !important
82 | border-bottom: 1px solid $primary-color !important
83 |
84 | .rdrDayStartPreview
85 | border-top-left-radius: 13px !important
86 | border-bottom-left-radius: 13px !important
87 | left: 3px
88 | border-left: 1px solid $primary-color !important
89 | border-top: 1px solid $primary-color !important
90 | border-bottom: 1px solid $primary-color !important
91 |
92 | .rdrDateDisplayWrapper
93 | display: none !important
94 |
95 | .rdrDefinedRangesWrapper
96 | display: none !important
97 |
--------------------------------------------------------------------------------
/src/styles/login.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 | .login
4 | height: 90vh
5 | background-color: #ff5a6048
6 | display: grid
7 | grid-template-columns: 50% 50%
8 | @media screen and (max-width:900px)
9 | grid-template-columns: 100%
10 | .form-group
11 | background-color: white
12 | display: flex
13 | flex-direction: column
14 | align-items: center
15 | .logo
16 | margin: 1em 0
17 | font-size: 2em
18 | .title
19 | margin: 1.5em 0 .5em 0
20 | font-size: 3em
21 | letter-spacing: 1px
22 | @media screen and (max-width :900px)
23 | font-size: 2em
24 | .form
25 | p
26 | font-size: 1em
27 | margin: 1.5em 0 .2em 0
28 | font-weight: 500
29 | input
30 | width: 350px
31 | height: 45px
32 | border-radius: 5px
33 | border: 1px solid #00000026
34 | padding: 20px
35 | &:focus
36 | border: 1px solid $primary-color
37 | outline: none
38 | .btn
39 | width: 350px
40 | height: 40px
41 | border: none
42 | border-radius: 5px
43 | background-color: $primary-color
44 | color: #ffffff
45 | margin-top: 2.5em
46 | cursor: pointer
47 | letter-spacing: 1px
48 | display: flex
49 | align-items: center
50 | justify-content: center
51 | .forget
52 | margin-left: 220px
53 | margin-top: 10px
54 | color: $primary-color
55 | font-size: .8em
56 | letter-spacing: 1px
57 | cursor: pointer
58 | .pwd-box
59 | position: relative
60 | .pwd-icon
61 | font-size: 1.5em
62 | position: absolute
63 | right: 10px
64 | top: 10px
65 | .devider
66 | height: 2px
67 | width: 350px
68 | background-color: #0000001a
69 | margin-top: 2em
70 | .dont
71 | margin-top: 1em
72 | color: grey
73 | span
74 | color: $primary-color
75 | .illustrations
76 | display: flex
77 | justify-content: center
78 | align-items: center
79 | @media screen and (max-width:900px)
80 | display: none
81 | img
82 | height: 90%
83 | width: 90%
84 |
85 | .forget
86 | background: none
87 |
88 | .question
89 | display: flex
90 | justify-content: center
91 | align-items: center
92 | @media screen and (max-width:900px)
93 | display: none
94 | img
95 | height: 70%
96 | width: 70%
97 |
--------------------------------------------------------------------------------
/src/styles/navbar.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 | .navbar
3 | height: 10vh
4 | display: flex
5 | align-items: center
6 | justify-content: space-between
7 | padding: 0 40px
8 | @media screen and (max-width:900px)
9 | padding: 0 50px
10 | .links
11 | display: flex
12 | p
13 | margin: 0 1em
14 | .search
15 | position: relative
16 | input
17 | width: 500px
18 | height: 45px
19 | border-radius: 5px
20 | border: 1px solid #00000026
21 | padding: 20px
22 | &:focus
23 | border: 1px solid $primary-color
24 | outline: none
25 | .icon-box
26 | position: absolute
27 | top: 0
28 | right: 0
29 | font-size: 1.5em
30 | height: 45px
31 | width: 50px
32 | display: flex
33 | justify-content: center
34 | align-items: center
35 | background-color: $primary-color
36 | border-top-right-radius: 5px
37 | border-bottom-right-radius: 5px
38 | color: #FFF
39 |
40 | .join
41 | button
42 | width: 150px
43 | height: 45px
44 | border: none
45 | border-radius: 5px
46 | background-color: $primary-color
47 | color: #ffffff
48 | cursor: pointer
49 | letter-spacing: 1px
50 | text-align: center
51 | font-weight: 600
52 | .drawer-icon
53 | font-size: 2em
54 |
55 |
56 | .drawer-body
57 | .search
58 | position: relative
59 | margin: 2em
60 |
61 | input
62 | width: 100%
63 | height: 45px
64 | border-radius: 5px
65 | border: 1px solid #00000026
66 | padding: 20px
67 | &:focus
68 | border: 1px solid $primary-color
69 | outline: none
70 | .icon-box
71 | position: absolute
72 | top: 0
73 | right: 0
74 | font-size: 1.5em
75 | height: 45px
76 | width: 50px
77 | display: flex
78 | justify-content: center
79 | align-items: center
80 | background-color: $primary-color
81 | border-top-right-radius: 5px
82 | border-bottom-right-radius: 5px
83 | color: #FFF
84 | .links
85 | display: flex
86 | justify-content: center
87 | align-items: center
88 | p
89 | margin: 0 1em
90 |
--------------------------------------------------------------------------------
/src/styles/profile.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 | .upload-file101
4 | height: 50px
5 | width: 100%
6 | margin-top: 20px
7 | background-color: #fff
8 | border: 1px solid $primary-color
9 | border-radius: 5px
10 | color: $primary-color
11 | display: flex
12 | justify-content: center
13 | align-items: center
14 | font-size: 1.2em
15 |
16 |
17 | .profilePicDiv
18 | border: 1px solid black
19 | height: 300px
20 | width: 60%
21 | margin: auto
22 | margin-top: 30px
23 | overflow: hidden
24 |
25 |
26 | .profilePic
27 | width: 100%
28 | height: 100%
29 |
30 |
31 | .favourite_items
32 | margin-top: 40px
33 |
34 |
35 |
36 | .btn
37 | width: 100%
38 | height: 45px
39 | border: none
40 | border-radius: 5px
41 | background-color: $primary-color
42 | color: #ffffff
43 | margin-top: 1.5em
44 | cursor: pointer
45 | letter-spacing: 1px
46 | display: flex
47 | align-items: center
48 | justify-content: center
--------------------------------------------------------------------------------
/src/styles/search.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 | .filters
4 | padding: 20px 50px
5 |
6 | .tab-list
7 | padding: 10px 10px
8 | overflow: auto
9 | white-space: nowrap
10 | -ms-overflow-style: none
11 | scrollbar-width: none
12 | .posts-grid
13 | margin-top: 20px
14 | display: grid
15 | grid-template-columns: repeat(4,1fr)
16 | gap: 20px
17 | @media screen and (max-width: 1200px)
18 | grid-template-columns: repeat(2,1fr)
19 | @media screen and (max-width: 760px)
20 | grid-template-columns: repeat(1,1fr)
21 | margin: auto
22 | .tab-list::-webkit-scrollbar
23 | display: none
24 |
25 |
26 | .image-box
27 | position: relative
28 | .heart
29 | height: 30px
30 | width: 30px
31 | background-color: #F7F5F2
32 | position: absolute
33 | top: 20px
34 | right: 20px
35 | display: flex
36 | justify-content: center
37 | align-items: center
38 | border-radius: 4px
39 | box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;
40 | cursor: pointer
41 | .heart-outline
42 | fill: $primary-color
43 | font-size: 22px
44 | img
45 | height: 100%
46 | width: 100%
47 |
48 |
49 |
--------------------------------------------------------------------------------
/src/styles/signup.sass:
--------------------------------------------------------------------------------
1 | @import "./_variables"
2 |
3 | .signup
4 | height: 90vh
5 | display: grid
6 | grid-template-columns: 45% 55%
7 | @media screen and (max-width:900px)
8 | grid-template-columns: 100%
9 | .form-group
10 | display: flex
11 | flex-direction: column
12 | align-items: center
13 | .logo
14 | margin: .6em 0
15 | font-size: 2em
16 | .title
17 | margin: .5em 0
18 | font-size: 2.5em
19 | letter-spacing: 1px
20 | @media screen and (max-width :900px)
21 | font-size: 2em
22 | .form
23 | .input-grp
24 | display: flex
25 | justify-content: space-between
26 | p
27 | font-size: 1em
28 | margin: 1em 0 .2em 0
29 | font-weight: 500
30 | input
31 | width: 200px
32 | height: 45px
33 | border-radius: 5px
34 | border: 1px solid #00000026
35 | padding: 20px
36 | &:focus
37 | border: 1px solid $primary-color
38 | outline: none
39 | input[type="file"]
40 | display: none
41 | .upload-file101
42 | height: 50px
43 | width: 100%
44 | margin-top: 20px
45 | background-color: #fff
46 | border: 1px solid $primary-color
47 | border-radius: 5px
48 | color: $primary-color
49 | display: flex
50 | justify-content: center
51 | align-items: center
52 | font-size: 1.2em
53 | .imagename
54 | font:
55 | size: 0.9em
56 | color: #2e2d2d
57 |
58 | .btn
59 | width: 100%
60 | height: 45px
61 | border: none
62 | border-radius: 5px
63 | background-color: $primary-color
64 | color: #ffffff
65 | margin-top: 1.5em
66 | cursor: pointer
67 | letter-spacing: 1px
68 | display: flex
69 | align-items: center
70 | justify-content: center
71 | .forget
72 | margin-left: 220px
73 | margin-top: 10px
74 | color: $primary-color
75 | font-size: .8em
76 | letter-spacing: 1px
77 | cursor: pointer
78 | .pwd-box
79 | position: relative
80 | .pwd-icon
81 | font-size: 1.5em
82 | position: absolute
83 | right: 10px
84 | top: 10px
85 |
86 | .devider
87 | height: 2px
88 | width: 350px
89 | background-color: #0000001a
90 | margin-top: 1.5em
91 | .dont
92 | margin-top: 1em
93 | color: grey
94 | span
95 | color: $primary-color
96 | .illustrations
97 | display: flex
98 | justify-content: center
99 | align-items: center
100 | @media screen and (max-width:900px)
101 | display: none
102 | img
103 | height: 80%
104 | width: 80%
105 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: [
3 | "./src/**/*.{js,jsx,ts,tsx}",
4 | ],
5 | theme: {
6 | extend: {},
7 | },
8 | plugins: [],
9 | }
--------------------------------------------------------------------------------