├── .gitignore
├── README.md
├── package.json
├── public
├── _redirects
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── src
├── assets
│ ├── carousel
│ │ ├── 1-new.jpg
│ │ ├── 2-new.jpg
│ │ ├── 3-new.jpg
│ │ └── 4-new.jpg
│ ├── categories
│ │ ├── 01.jpg
│ │ ├── 02.jpg
│ │ ├── 03.jpg
│ │ ├── 04.jpg
│ │ ├── 05.jpg
│ │ ├── 06.jpg
│ │ └── 07.jpg
│ ├── img-1.jpg
│ ├── nav-logo.png
│ ├── project
│ │ ├── 01.jpeg
│ │ ├── 02.jpeg
│ │ ├── 03.jpeg
│ │ └── 04.jpeg
│ └── services
│ │ └── services-new.jpg
├── components
│ ├── about
│ │ └── About.jsx
│ ├── carousel
│ │ └── CarouselContainer.jsx
│ ├── footer
│ │ └── Footer.jsx
│ ├── navbar
│ │ └── Navbar.jsx
│ └── services
│ │ └── Services.jsx
├── config
│ └── firebase
│ │ └── firebase-config.js
├── index.css
├── index.js
├── pages
│ ├── auth
│ │ └── Login.jsx
│ ├── contact
│ │ └── ContactUs.jsx
│ ├── dashboard
│ │ ├── DashboardHome.jsx
│ │ ├── DashboardProjects.jsx
│ │ └── DashboardProjectsAdd.jsx
│ ├── home
│ │ └── HomePage.jsx
│ ├── projects
│ │ └── ProjectsPage.jsx
│ └── services
│ │ └── ServicesPage.jsx
└── routes
│ ├── ClientRoutes.jsx
│ └── router.js
└── 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 | package-lock.json
8 | /.idea
9 |
10 | # testing
11 | /coverage
12 |
13 | # production
14 | /build
15 |
16 | # misc
17 | .DS_Store
18 | .env.local
19 | .env.development.local
20 | .env.test.local
21 | .env.production.local
22 |
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # glimpseofdesign-frontend
2 | This repo contains the folder of front end development of the Glimpse of design website
3 |
4 | This is official Glimpse of Design Website
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "glimpse-frontend-new",
3 | "version": "1.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emailjs/browser": "^3.10.0",
7 | "@emotion/react": "^11.10.5",
8 | "@emotion/styled": "^11.10.5",
9 | "@firebase/firestore": "^3.8.0",
10 | "@headlessui/react": "^1.7.7",
11 | "@heroicons/react": "^2.0.13",
12 | "@react-icons/all-files": "^4.1.0",
13 | "@testing-library/jest-dom": "^5.16.5",
14 | "@testing-library/react": "^13.4.0",
15 | "@testing-library/user-event": "^13.5.0",
16 | "firebase": "^9.15.0",
17 | "formik": "^2.2.9",
18 | "react": "^18.2.0",
19 | "react-dom": "^18.2.0",
20 | "react-icons": "^4.7.1",
21 | "react-multi-carousel": "^2.8.2",
22 | "react-paginate": "^8.1.4",
23 | "react-router-dom": "^6.6.2",
24 | "react-scripts": "5.0.1",
25 | "react-spinners": "^0.13.8",
26 | "styled-components": "^5.3.6",
27 | "sweetalert2": "^11.7.0",
28 | "uuid": "^9.0.0",
29 | "web-vitals": "^2.1.4",
30 | "yup": "^0.32.11"
31 | },
32 | "scripts": {
33 | "start": "react-scripts start",
34 | "build": "react-scripts build",
35 | "test": "react-scripts test",
36 | "eject": "react-scripts eject"
37 | },
38 | "eslintConfig": {
39 | "extends": [
40 | "react-app",
41 | "react-app/jest"
42 | ]
43 | },
44 | "browserslist": {
45 | "production": [
46 | ">0.2%",
47 | "not dead",
48 | "not op_mini all"
49 | ],
50 | "development": [
51 | "last 1 chrome version",
52 | "last 1 firefox version",
53 | "last 1 safari version"
54 | ]
55 | },
56 | "devDependencies": {
57 | "tailwindcss": "^3.2.4"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/public/_redirects:
--------------------------------------------------------------------------------
1 | /* /index.html 200
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/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 |
--------------------------------------------------------------------------------
/src/assets/carousel/1-new.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/carousel/1-new.jpg
--------------------------------------------------------------------------------
/src/assets/carousel/2-new.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/carousel/2-new.jpg
--------------------------------------------------------------------------------
/src/assets/carousel/3-new.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/carousel/3-new.jpg
--------------------------------------------------------------------------------
/src/assets/carousel/4-new.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/carousel/4-new.jpg
--------------------------------------------------------------------------------
/src/assets/categories/01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/01.jpg
--------------------------------------------------------------------------------
/src/assets/categories/02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/02.jpg
--------------------------------------------------------------------------------
/src/assets/categories/03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/03.jpg
--------------------------------------------------------------------------------
/src/assets/categories/04.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/04.jpg
--------------------------------------------------------------------------------
/src/assets/categories/05.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/05.jpg
--------------------------------------------------------------------------------
/src/assets/categories/06.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/06.jpg
--------------------------------------------------------------------------------
/src/assets/categories/07.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/categories/07.jpg
--------------------------------------------------------------------------------
/src/assets/img-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/img-1.jpg
--------------------------------------------------------------------------------
/src/assets/nav-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/nav-logo.png
--------------------------------------------------------------------------------
/src/assets/project/01.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/project/01.jpeg
--------------------------------------------------------------------------------
/src/assets/project/02.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/project/02.jpeg
--------------------------------------------------------------------------------
/src/assets/project/03.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/project/03.jpeg
--------------------------------------------------------------------------------
/src/assets/project/04.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/project/04.jpeg
--------------------------------------------------------------------------------
/src/assets/services/services-new.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Glimpse-of-Design/glimpseofdesign-frontend/2b9d6b6fc48ded91c46d83c4629c56b8e3d3b8e3/src/assets/services/services-new.jpg
--------------------------------------------------------------------------------
/src/components/about/About.jsx:
--------------------------------------------------------------------------------
1 | const About = () => {
2 | return (
3 |
4 |
6 |
7 |
8 | About Us
9 |
10 |
11 |
12 |
13 |
14 |
15 | Who we are
16 |
17 |
18 | We are an interior design firm that creates unique interiors which
19 | builts functionality and easthetic apearance with a Glimpse to win
20 | clients hearts.
21 |
22 |
23 |
24 |
29 |
30 |
31 |
32 | );
33 | };
34 |
35 | export default About;
36 |
--------------------------------------------------------------------------------
/src/components/carousel/CarouselContainer.jsx:
--------------------------------------------------------------------------------
1 | import Carousel from 'react-multi-carousel';
2 | import 'react-multi-carousel/lib/styles.css';
3 | import img1 from '../../assets/carousel/1-new.jpg';
4 | import img2 from '../../assets/carousel/2-new.jpg';
5 | import img3 from '../../assets/carousel/3-new.jpg';
6 | import img4 from '../../assets/carousel/4-new.jpg';
7 |
8 | const responsiveImageHero = {
9 | desktop: {
10 | breakpoint: {max: 3000, min: 1024},
11 | items: 1
12 | },
13 | tablet: {
14 | breakpoint: {max: 1024, min: 464},
15 | items: 1
16 | },
17 | mobile: {
18 | breakpoint: {max: 464, min: 0},
19 | items: 1
20 | }
21 | };
22 |
23 | const images = [
24 | img1, img2, img3, img4
25 | ];
26 |
27 | const CarouselContainer = () => {
28 | return (
29 |
36 | {images.slice(0, 4).map((image, id) => {
37 | return (
38 |
50 | );
51 | })}
52 |
53 | );
54 | }
55 |
56 | export default CarouselContainer;
57 |
--------------------------------------------------------------------------------
/src/components/footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import {onAuthStateChanged} from 'firebase/auth';
2 | import {useEffect, useState} from 'react';
3 | import {Link} from 'react-router-dom';
4 | import {auth} from '../../config/firebase/firebase-config';
5 |
6 | const Footer = () => {
7 | const [user, setUser] = useState({});
8 |
9 | useEffect(() => {
10 | onAuthStateChanged(auth, (currentUser) => {
11 | setUser(currentUser);
12 | });
13 | }, [user]);
14 | return (
15 |
161 | )
162 | }
163 |
164 | export default Footer;
165 |
--------------------------------------------------------------------------------
/src/components/navbar/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import {Disclosure, Menu, Transition} from '@headlessui/react';
2 | import {Bars3Icon, XMarkIcon} from '@heroicons/react/24/outline';
3 | import {onAuthStateChanged, signOut} from 'firebase/auth';
4 | import {Fragment, useEffect, useState} from 'react';
5 | import {Link, NavLink} from 'react-router-dom';
6 | import navLogo from '../../assets/nav-logo.png';
7 | import {auth} from '../../config/firebase/firebase-config';
8 |
9 | const navigation = [
10 | {name: 'HOME', to: '/', current: false},
11 | {name: 'PROJECTS', to: '/projects', current: false},
12 | {name: 'SERVICES', to: '/services', current: false},
13 | {name: 'CONTACT US', to: '/contact', current: false},
14 | ]
15 |
16 | function classNames(...classes) {
17 | return classes.filter(Boolean).join(' ')
18 | }
19 |
20 | const logout = async () => {
21 | await signOut(auth);
22 | };
23 |
24 | export default function Navbar() {
25 | const [user, setUser] = useState({});
26 |
27 | useEffect(() => {
28 | onAuthStateChanged(auth, (currentUser) => {
29 | setUser(currentUser);
30 | });
31 | }, [user]);
32 |
33 | return (
34 |
35 | {({open}) => (
36 | <>
37 |
38 |
39 |
40 | {/* Mobile menu button*/}
41 |
43 | Open main menu
44 | {open ? (
45 |
46 | ) : (
47 |
48 | )}
49 |
50 |
51 |
53 |
54 |
59 |
64 |
65 |
67 |
68 | {navigation.map((item) => (
69 |
75 | {item.name}
76 |
77 | ))}
78 |
79 |
80 |
81 |
82 | {user && (
83 |
85 |
86 | {/* Profile dropdown */}
87 |
88 |
89 |
91 | Open user menu
92 |
97 |
98 |
99 |
108 |
110 |
111 | {({active}) => (
112 |
116 | Dashboard
117 |
118 | )}
119 |
120 |
121 | {({active}) => (
122 |
126 | Sign out
127 |
128 | )}
129 |
130 |
131 |
132 |
133 |
134 | )}
135 |
136 |
137 |
138 | {/*Mobile View*/}
139 |
140 |
141 | {navigation.map((item) => (
142 |
149 | {item.name}
150 |
151 | ))}
152 |
153 |
154 | >
155 | )}
156 |
157 | )
158 | }
159 |
--------------------------------------------------------------------------------
/src/components/services/Services.jsx:
--------------------------------------------------------------------------------
1 | import {BsArrowRight} from 'react-icons/bs';
2 | import {Link} from 'react-router-dom';
3 |
4 | const Services = () => {
5 | return (
6 |
7 |
9 |
10 |
11 | Services
12 |
13 |
14 |
15 |
16 |
17 |
22 |
23 |
24 |
25 | What we do
26 |
27 |
28 | Our services in design process are always flexible to reach clients
29 | budgets. This includes layout planning, moodboard visualizing, 3D
30 | visualizing, technical detailing, Colour and Material selecting,
31 | Furniture Selecting and finally Accessorizing.
32 |
33 |
34 |
36 |
37 | Explore
38 |
39 |
40 |
41 |
42 |
43 |
44 | );
45 | };
46 |
47 | export default Services;
48 |
--------------------------------------------------------------------------------
/src/config/firebase/firebase-config.js:
--------------------------------------------------------------------------------
1 | import {getFirestore} from '@firebase/firestore';
2 | import {getAnalytics} from 'firebase/analytics';
3 | import {initializeApp} from 'firebase/app';
4 | import {getAuth} from 'firebase/auth';
5 | import {getStorage} from 'firebase/storage';
6 |
7 | const firebaseConfig = {
8 | apiKey: 'AIzaSyDjPNj3UUd87nOJViI6cop1SjZ5o8hQRCE',
9 | authDomain: 'glimpseofdesign-backend.firebaseapp.com',
10 | projectId: 'glimpseofdesign-backend',
11 | storageBucket: 'glimpseofdesign-backend.appspot.com',
12 | messagingSenderId: '259832056346',
13 | appId: '1:259832056346:web:084370a87c57f5f266dfa3',
14 | measurementId: 'G-B5WGR8G115'
15 | };
16 |
17 | const app = initializeApp(firebaseConfig);
18 | export const db = getFirestore();
19 | export const storage = getStorage(app);
20 | export const auth = getAuth(app);
21 |
22 | getAnalytics(app);
23 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | @layer components {
6 | .active {
7 | background-color: #d9a527;
8 | color: white;
9 | }
10 |
11 | .text-error {
12 | color: red;
13 | }
14 | .carouselContainer{
15 | margin: 0 auto;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import {RouterProvider} from 'react-router-dom';
4 | import './index.css';
5 | import router from './routes/router';
6 |
7 | const root = ReactDOM.createRoot(document.getElementById('root'));
8 |
9 | root.render(
10 |
11 |
12 |
13 | );
14 |
--------------------------------------------------------------------------------
/src/pages/auth/Login.jsx:
--------------------------------------------------------------------------------
1 | import {onAuthStateChanged, signInWithEmailAndPassword} from 'firebase/auth';
2 | import {Field, Form, Formik} from 'formik';
3 | import React, {useState} from 'react';
4 | import {useNavigate} from 'react-router-dom';
5 | import Swal from 'sweetalert2';
6 | import * as Yup from 'yup';
7 | import logo from '../../assets/nav-logo.png';
8 | import {auth} from '../../config/firebase/firebase-config';
9 |
10 | const DisplayingErrorMessagesSchema = Yup.object().shape({
11 | email: Yup.string()
12 | .min(2, 'Too Short!')
13 | .max(50, 'Too Long!')
14 | .required('Required'),
15 | password: Yup.string()
16 | .min(2, 'Too Short!')
17 | .max(50, 'Too Long!')
18 | .required('Required'),
19 | });
20 |
21 | const Login = () => {
22 | const [, setUser] = useState({});
23 | const navigate = useNavigate();
24 |
25 | onAuthStateChanged(auth, (currentUser) => {
26 | setUser(currentUser);
27 | });
28 |
29 | return (
30 |
31 |
Displaying Error Messages
32 |
{
39 | const login = async () => {
40 | try {
41 | await signInWithEmailAndPassword(
42 | auth,
43 | values.email,
44 | values.password
45 | );
46 | await Swal.fire({
47 | position: 'top-end',
48 | title: 'Successfully logged in',
49 | showConfirmButton: false,
50 | timer: 1500,
51 | });
52 | navigate('/dashboard/projects');
53 | } catch (e) {
54 | await Swal.fire({
55 | position: 'top-end',
56 | icon: 'error',
57 | title: 'Your Username or password incorrect',
58 | showConfirmButton: false,
59 | timer: 1500,
60 | });
61 | navigate('/login');
62 | }
63 | }
64 | login().then();
65 | }}
66 | >
67 | {({errors, touched}) => (
68 |
123 | )}
124 |
125 |
126 | );
127 | };
128 |
129 | export default Login;
130 |
--------------------------------------------------------------------------------
/src/pages/contact/ContactUs.jsx:
--------------------------------------------------------------------------------
1 | import emailjs from '@emailjs/browser';
2 | import React, {useRef, useState} from 'react';
3 | import {FaPhoneAlt} from 'react-icons/fa';
4 | import {MdEmail} from 'react-icons/md';
5 | import {useNavigate} from 'react-router-dom';
6 | import Swal from 'sweetalert2';
7 |
8 | const ContactUs = () => {
9 | const [pressedEmail, setPressedEmail] = useState(false);
10 | const navigate = useNavigate();
11 |
12 | const form = useRef();
13 |
14 | const sendEmail = (e) => {
15 | e.preventDefault();
16 |
17 | emailjs.sendForm('service_o5gc3lh', 'template_jk9ypea', form.current, '2ZGngDdyigPc-3rlJ')
18 | .then((result) => {
19 | Swal.fire({
20 | position: 'top-end',
21 | title: 'Email Sent Successfully',
22 | showConfirmButton: false,
23 | timer: 1500,
24 | }).then();
25 | navigate("/");
26 | console.log(result.text);
27 | }, (error) => {
28 | Swal.fire({
29 | position: 'top-end',
30 | icon: 'error',
31 | title: 'Email Send Error',
32 | showConfirmButton: false,
33 | timer: 1500,
34 | }).then();
35 | console.log(error.text);
36 | });
37 | };
38 |
39 | return (
40 |
41 | {!pressedEmail && (
42 |
43 |
44 |
45 | Contact us
46 |
47 |
48 | Need to get in touch with us?
49 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
Phone:
58 |
+94 71 7662323
59 |
60 |
setPressedEmail(!pressedEmail)}>
62 |
64 |
65 |
66 |
Email:
67 |
glimpseofdesign@gmail.com
68 |
69 |
70 |
71 | )}
72 |
73 | {pressedEmail && (
74 |
75 |
76 |
77 |
78 |
79 | Contact us
80 |
81 |
82 | Need to get in touch with us?
83 |
84 |
85 |
135 |
136 |
137 |
138 | )}
139 |
140 | )
141 | }
142 | export default ContactUs;
143 |
--------------------------------------------------------------------------------
/src/pages/dashboard/DashboardHome.jsx:
--------------------------------------------------------------------------------
1 | import {Menu, Transition} from '@headlessui/react';
2 | import {signOut} from 'firebase/auth';
3 | import {collection, getDocs} from 'firebase/firestore';
4 | import {Fragment, useEffect, useState} from 'react';
5 | import {Link, NavLink, Outlet, useNavigate} from 'react-router-dom';
6 | import navLogo from '../../assets/nav-logo.png';
7 | import {auth, db} from '../../config/firebase/firebase-config';
8 |
9 | const projectsCollectionRef = collection(db, 'projects');
10 |
11 | const DashboardHome = () => {
12 | const [projects, setProjects] = useState([]);
13 | const navigate = useNavigate();
14 |
15 | const getProjects = async () => {
16 | const data = await getDocs(projectsCollectionRef);
17 | setProjects(data.docs.map((doc) => ({...doc.data(), id: doc.id})));
18 | };
19 |
20 | const logout = async () => {
21 | await signOut(auth);
22 | navigate('/');
23 | };
24 |
25 | useEffect(() => {
26 | getProjects().catch((err) => console.log(err));
27 | }, []);
28 |
29 | return (
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
44 |
47 |
49 |
51 |
52 | Projects
53 | {projects.length}
55 |
56 |
57 |
58 |
60 |
63 |
65 |
67 |
68 | Add Projects
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
82 |
83 |
84 | Dashboard
85 |
86 |
87 |
88 |
90 |
91 | {/* Profile dropdown */}
92 |
93 |
94 |
96 | Open user menu
97 |
102 |
103 |
104 |
113 |
115 |
116 |
120 | Go to Home
121 |
122 |
123 |
124 |
128 | Sign out
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | Projects
141 | {projects.length}
143 |
144 |
148 | Add Projects
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 | )
158 | }
159 |
160 | export default DashboardHome;
161 |
--------------------------------------------------------------------------------
/src/pages/dashboard/DashboardProjects.jsx:
--------------------------------------------------------------------------------
1 | import {Menu, Transition} from '@headlessui/react';
2 | import {collection, deleteDoc, doc, getDoc, getDocs, updateDoc} from 'firebase/firestore';
3 | import {Field, Form, Formik, useField} from 'formik';
4 | import React, {Fragment, useEffect, useState} from 'react';
5 | import {AiOutlineClose} from 'react-icons/ai';
6 | import ReactPaginate from 'react-paginate';
7 | import Swal from 'sweetalert2';
8 | import * as Yup from 'yup';
9 | import img1 from '../../assets/project/01.jpeg';
10 | import {db} from '../../config/firebase/firebase-config';
11 |
12 | const projectsCollectionRef = collection(db, 'projects');
13 | const PER_PAGE = 6;
14 |
15 | const DisplayingErrorMessagesSchema = Yup.object().shape({
16 | projectName: Yup.string()
17 | .min(2, 'Too Short!')
18 | .max(50, 'Too Long!')
19 | .required('Required'),
20 | projectSummary: Yup.string()
21 | .min(2, 'Too Short!')
22 | .max(50, 'Too Long!')
23 | .required('Required'),
24 | });
25 |
26 | const MyTextArea = ({label, ...props}) => {
27 | const [field, meta] = useField(props);
28 | return (
29 | <>
30 | {label}
31 |
32 | {meta.touched && meta.error ? (
33 | {meta.error}
34 | ) : null}
35 | >
36 | );
37 | };
38 |
39 | const DashboardProjects = () => {
40 | const [projects, setProjects] = useState([]);
41 | const [projectId, setProjectId] = useState('');
42 | const [currentPage, setCurrentPage] = useState(0);
43 | const [showModal, setShowModal] = useState(false);
44 | const [project, setProject] = useState({
45 | projectSummary: '',
46 | projectName: '',
47 | description: '',
48 | images: [{
49 | url: '../../assets/project/01.jpeg',
50 | }]
51 | });
52 |
53 | const offset = currentPage * PER_PAGE;
54 | const pageCount = Math.ceil(projects.length / PER_PAGE);
55 | const handlePageClick = ({selected: selectedPage}) => {
56 | setCurrentPage(selectedPage);
57 | };
58 | const deleteProject = async (id) => {
59 | const projectDoc = await doc(db, 'projects', id);
60 |
61 | Swal.fire({
62 | title: 'Are you sure?',
63 | text: 'You won\'t be able to revert this!',
64 | icon: 'warning',
65 | showCancelButton: true,
66 | confirmButtonColor: '#3085d6',
67 | cancelButtonColor: '#dd3333',
68 | confirmButtonText: 'Yes, delete it!'
69 | }).then((result) => {
70 | if (result.isConfirmed) {
71 | Swal.fire(
72 | 'Deleted!',
73 | 'Your file has been deleted.',
74 | 'success'
75 | )
76 | deleteDoc(projectDoc);
77 | getProjects().catch((err) => console.log(err));
78 | }
79 | })
80 | }
81 | const getProjects = async () => {
82 | const data = await getDocs(projectsCollectionRef);
83 | setProjects(data.docs.map((doc) => ({...doc.data(), id: doc.id})));
84 | };
85 | const getProject = async (id) => {
86 | const projectDoc = doc(db, 'projects', id);
87 | const dSnap = await getDoc(projectDoc);
88 | if (dSnap.exists()) {
89 | const data = dSnap.data();
90 | setProject(data);
91 | setProjectId(dSnap.id);
92 | }
93 | }
94 |
95 | useEffect(() => {
96 | getProjects().catch((err) => console.log(err));
97 | }, []);
98 |
99 | return (
100 |
101 |
102 |
103 |
104 |
105 | Project Name
106 |
107 |
108 | Project Summery
109 |
110 |
111 | Description
112 |
113 |
114 | Images
115 |
116 |
117 |
118 |
119 | {
120 | projects.length !== 0 && projects
121 | .slice(offset, offset + PER_PAGE)
122 | .map(({projectName, projectSummary, description, id, images}) => (
123 |
124 |
125 |
126 | {projectName}
127 |
128 |
129 |
130 |
131 | {projectSummary}
132 |
133 |
134 |
135 |
136 | {description}
137 |
138 |
139 |
140 |
141 | {images.map((image, id) => (
142 |
143 | ))}
144 |
145 |
146 |
147 | {showModal ? (
148 | <>
149 |
152 |
153 | {/*content*/}
154 |
156 | {/*header*/}
157 |
159 |
160 | Update Project
161 |
162 |
setShowModal(false)}
165 | >
166 |
167 |
168 | {/*body*/}
169 |
170 |
{
180 | try {
181 | const updateProject = async () => {
182 | const projectDoc = doc(db, 'projects', projectId);
183 | await updateDoc(projectDoc, {
184 | projectName: values.projectName,
185 | projectSummary: values.projectSummary,
186 | description: values.description,
187 | })
188 | }
189 | updateProject().then();
190 | setShowModal(false);
191 | getProjects().then();
192 | } catch (e) {
193 | Swal.fire({
194 | icon: 'error',
195 | title: 'Oops...',
196 | text: 'Update Error!',
197 | footer: 'Why do I have this issue? ',
198 | }).then();
199 | }
200 | }}
201 | >
202 | {({errors, touched}) => (
203 |
204 |
205 |
207 |
208 |
209 |
210 |
211 | Project Name
212 |
213 |
217 | {touched.projectName && errors.projectName &&
218 |
{errors.projectName}
}
220 |
221 |
222 |
223 | Project Summary
224 |
225 |
229 | {touched.projectSummary && errors.projectSummary &&
230 |
{errors.projectSummary}
}
232 |
233 |
234 |
235 |
236 |
244 |
245 |
246 |
247 |
248 | Photos of Location
249 |
250 |
251 | {project ? project.images.map((image, id) => (
252 |
254 |
257 |
259 |
260 | )) : null}
261 |
262 |
263 |
264 |
266 |
269 | Update Project
270 |
271 |
272 |
273 |
274 |
275 |
276 | )}
277 |
278 |
279 |
280 |
281 |
282 |
283 | >
284 | ) : null}
285 |
286 |
288 |
289 |
290 |
292 | Open user menu
293 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
317 |
319 |
320 | {
323 | setShowModal(true);
324 | getProject(id).then();
325 | }}>
326 | Edit
327 |
328 |
329 |
330 | {
333 | deleteProject(id).then()
334 | }}
335 | >
336 | Delete
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 | ))
347 |
348 | }
349 |
350 |
351 |
371 |
372 | )
373 | }
374 |
375 | export default DashboardProjects;
376 |
--------------------------------------------------------------------------------
/src/pages/dashboard/DashboardProjectsAdd.jsx:
--------------------------------------------------------------------------------
1 | import {addDoc, collection} from 'firebase/firestore';
2 | import {getDownloadURL, ref, uploadBytes} from 'firebase/storage';
3 | import {Field, Form, Formik, useField} from 'formik';
4 | import React, {useState} from 'react';
5 | import {useNavigate} from 'react-router-dom';
6 | import Swal from 'sweetalert2';
7 | import {v4} from 'uuid';
8 | import * as Yup from 'yup';
9 | import {db, storage} from '../../config/firebase/firebase-config';
10 |
11 | const projectsCollectionRef = collection(db, 'projects');
12 |
13 | const DisplayingErrorMessagesSchema = Yup.object().shape({
14 | projectName: Yup.string()
15 | .min(2, 'Too Short!')
16 | .max(50, 'Too Long!')
17 | .required('Required'),
18 | projectSummary: Yup.string()
19 | .min(2, 'Too Short!')
20 | .max(50, 'Too Long!')
21 | .required('Required'),
22 | });
23 |
24 | const MyTextArea = ({label, ...props}) => {
25 | const [field, meta] = useField(props);
26 | return (
27 | <>
28 | {label}
29 |
30 | {meta.touched && meta.error ? (
31 | {meta.error}
32 | ) : null}
33 | >
34 | );
35 | };
36 |
37 | const DashboardProjectsAdd = () => {
38 | const navigate = useNavigate();
39 | const [images, setImages] = useState([]);
40 | const [urls, setUrls] = useState([]);
41 | const handleChange = (e) => {
42 | const preview = document.querySelector('#preview');
43 | const files = e.target.files;
44 |
45 | function readAndPreview(file) {
46 | const reader = new FileReader();
47 |
48 | reader.addEventListener('load', () => {
49 | const image = new Image();
50 | image.height = 100;
51 | image.width = 100;
52 | image.style.display = 'inline';
53 | image.title = file.name;
54 | image.src = String(reader.result);
55 | preview.appendChild(image);
56 | }, false);
57 | reader.readAsDataURL(file);
58 | }
59 |
60 | if (files) {
61 | Array.prototype.forEach.call(files, readAndPreview);
62 | }
63 |
64 | for (let i = 0; i < e.target.files.length; i++) {
65 | const newImage = e.target.files[i];
66 | newImage['id'] = Math.random();
67 | setImages((prevState) => [...prevState, newImage])
68 | }
69 | };
70 | const handleUpload = () => {
71 | images.map((image) => {
72 | const uploadTask = ref(storage, `images/${'img' + v4()}`);
73 | uploadBytes(uploadTask, image)
74 | .then((snapshot) => {
75 | getDownloadURL(snapshot.ref).then((url) => {
76 | setUrls((prev) => [...prev, url]);
77 | });
78 | })
79 | .catch(() => {
80 | Swal.fire({
81 | icon: 'error',
82 | title: 'Oops...',
83 | text: 'Something went wrong!',
84 | footer: 'Why do I have this issue? ',
85 | }).then();
86 | });
87 | return null;
88 | });
89 | }
90 |
91 | return (
92 |
93 |
{
103 | const obj = urls.map((url) => ({url}));
104 |
105 | try {
106 | const createProject = async () => {
107 | await addDoc(projectsCollectionRef, {
108 | projectName: values.projectName,
109 | projectSummary: values.projectSummary,
110 | description: values.description,
111 | images: obj
112 | });
113 | }
114 | createProject().catch((err) => console.log(err));
115 | navigate('/dashboard/projects');
116 | } catch (e) {
117 | Swal.fire({
118 | icon: 'error',
119 | title: 'Oops...',
120 | text: 'Something went wrong!',
121 | footer: 'Why do I have this issue? ',
122 | }).then();
123 | }
124 | }}
125 | >
126 | {({errors, touched}) => (
127 |
128 |
129 |
130 |
131 |
Add Project
132 |
133 |
134 |
135 | Project Name
136 |
137 |
139 | {touched.projectName && errors.projectName &&
140 |
{errors.projectName}
}
141 |
142 |
143 |
144 | Project Summary
145 |
146 |
148 | {touched.projectSummary && errors.projectSummary &&
149 |
{errors.projectSummary}
}
150 |
151 |
152 |
153 |
154 |
162 |
163 |
164 |
165 |
166 | Photos of Location
167 |
168 |
170 |
171 | {!urls && (
172 |
179 |
185 |
186 | )}
187 |
188 |
192 | {urls && Select Images }
193 |
203 |
204 |
205 |
206 |
207 |
208 | {urls.length === 0 && (
209 |
210 | PNG, JPG, GIF up to 10MB
211 |
212 | )}
213 | {images.length !== 0 && (
214 |
217 | Upload
218 |
219 | )}
220 |
221 |
222 |
223 |
224 |
225 | {urls.length !== 0 && (
226 |
229 | SUBMIT
230 |
231 | )}
232 |
233 |
234 |
235 |
236 |
237 | )}
238 |
239 |
240 | )
241 |
242 | };
243 |
244 |
245 | export default DashboardProjectsAdd;
246 |
--------------------------------------------------------------------------------
/src/pages/home/HomePage.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import About from '../../components/about/About';
3 | import CarouselContainer from '../../components/carousel/CarouselContainer';
4 | import Services from '../../components/services/Services';
5 |
6 | const HomePage = () => {
7 | return (
8 |
13 | )
14 | }
15 |
16 | export default HomePage;
17 |
--------------------------------------------------------------------------------
/src/pages/projects/ProjectsPage.jsx:
--------------------------------------------------------------------------------
1 | import {BsArrowRight} from '@react-icons/all-files/bs/BsArrowRight';
2 | import {collection, getDocs} from 'firebase/firestore';
3 | import {useEffect, useState} from 'react';
4 | import {PropagateLoader} from 'react-spinners';
5 |
6 | import img1 from '../../assets/project/01.jpeg';
7 | import {db} from '../../config/firebase/firebase-config';
8 |
9 | const projectsCollectionRef = collection(db, 'projects');
10 | const ProjectsPage = () => {
11 | const [noOfElements, setNoOfElements] = useState(6);
12 | const [projects, setProjects] = useState([]);
13 | const [loading, setLoading] = useState(true);
14 | const loadMore = () => {
15 | if (noOfElements <= projects.length) {
16 | setNoOfElements(noOfElements + noOfElements);
17 | } else {
18 | setNoOfElements(projects.length);
19 | }
20 | };
21 |
22 | const sliceArr = projects.slice(0, noOfElements);
23 |
24 | useEffect(() => {
25 | const getProjects = async () => {
26 | const data = await getDocs(projectsCollectionRef);
27 | setProjects(data.docs.map((doc) => ({...doc.data(), id: doc.id})));
28 | };
29 | getProjects().then(() => {
30 | setLoading(false);
31 | }
32 | );
33 |
34 | }, []);
35 |
36 | return (
37 |
38 |
40 |
41 |
42 | Projects
43 |
44 |
45 | We deliver your desire. Trusted for many years.
46 |
47 |
48 |
49 | {
50 | loading ?
: (
59 |
60 |
62 | {
63 | projects.length !== 0 &&
64 | sliceArr.map((project) => (
65 |
66 |
70 |
72 |
74 |
75 | {project.projectName}
76 |
77 |
78 |
80 |
81 | {project.projectSummary}
82 |
83 |
84 |
85 | ))}
86 |
87 | {
88 | projects.length !== noOfElements && (
89 |
91 |
loadMore()}
92 | className="flex flex-row flex-nowrap items-center">Explore
94 |
95 | )
96 | }
97 |
98 | )
99 | }
100 |
101 |
102 | )
103 | }
104 |
105 | export default ProjectsPage;
106 |
--------------------------------------------------------------------------------
/src/pages/services/ServicesPage.jsx:
--------------------------------------------------------------------------------
1 | import image1 from '../../assets/categories/01.jpg';
2 | import image2 from '../../assets/categories/02.jpg';
3 | import image3 from '../../assets/categories/03.jpg';
4 | import image4 from '../../assets/categories/04.jpg';
5 | import image5 from '../../assets/categories/05.jpg';
6 | import cover_img from '../../assets/services/services-new.jpg';
7 |
8 | const ServicesPage = () => {
9 | return (
10 |
11 |
12 |
13 |
14 |
19 |
24 |
29 |
30 |
32 |
33 | Services
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | What we do
44 |
45 |
46 | We deliver your desire. Trusted for many years.
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
59 |
61 |
62 | Designing
63 |
64 |
65 | {/*
66 |
67 | This is not a true content. A text used to describe the
68 | picture.
69 |
70 |
*/}
71 |
73 |
74 |
75 |
76 |
81 |
83 |
84 | 3D Visualizing
85 |
86 |
87 | {/*
88 |
89 | This is not a true content. A text used to describe the
90 | picture.
91 |
92 |
*/}
93 |
95 |
96 |
97 |
102 |
104 |
105 | Moodboards
106 |
107 |
108 | {/*
109 |
110 | This is not a true content. A text used to describe the
111 | picture.
112 |
113 |
*/}
114 |
116 |
117 |
118 |
119 |
120 |
125 |
127 |
128 | Fabricator Guiding
129 |
130 |
131 | {/*
132 |
133 | This is not a true content. A text used to describe the
134 | picture.
135 |
136 |
*/}
137 |
139 |
140 |
141 |
146 |
148 |
149 | Accessorizing
150 |
151 |
152 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | )
163 | }
164 |
165 | export default ServicesPage;
166 |
--------------------------------------------------------------------------------
/src/routes/ClientRoutes.jsx:
--------------------------------------------------------------------------------
1 | import {Outlet} from 'react-router-dom';
2 | import Footer from '../components/footer/Footer';
3 | import Navbar from '../components/navbar/Navbar';
4 |
5 | const ClientRoutes = () => {
6 |
7 | return (
8 | <>
9 |
10 |
11 |
12 | >
13 | )
14 | }
15 |
16 | export default ClientRoutes;
17 |
--------------------------------------------------------------------------------
/src/routes/router.js:
--------------------------------------------------------------------------------
1 | import {createBrowserRouter} from 'react-router-dom';
2 | import Login from '../pages/auth/Login';
3 | import ContactUs from '../pages/contact/ContactUs';
4 | import DashboardHome from '../pages/dashboard/DashboardHome';
5 | import DashboardProjects from '../pages/dashboard/DashboardProjects';
6 | import DashboardProjectsAdd from '../pages/dashboard/DashboardProjectsAdd';
7 | import HomePage from '../pages/home/HomePage';
8 | import ProjectsPage from '../pages/projects/ProjectsPage';
9 | import ServicesPage from '../pages/services/ServicesPage';
10 | import ClientRoutes from './ClientRoutes';
11 |
12 | const router = createBrowserRouter([
13 | {
14 | path: '/',
15 | element: ,
16 | children: [
17 | {
18 | path: '',
19 | element:
20 | },
21 | {
22 | path: 'projects',
23 | element:
24 | },
25 | {
26 | path: 'services',
27 | element:
28 | },
29 | {
30 | path: 'contact',
31 | element:
32 | }
33 | ]
34 | },
35 | {
36 | path: 'login',
37 | element: ,
38 | },
39 | {
40 | path: 'dashboard',
41 | element: ,
42 | children: [
43 | {
44 | path: 'projects',
45 | element:
46 | },
47 | {
48 | path: 'add',
49 | element:
50 | }
51 | ]
52 | },
53 | ]);
54 |
55 | export default router;
56 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | './src/**/*.{js,jsx,ts,tsx}',
5 | ],
6 | theme: {
7 | extend: {
8 | colors: {
9 | primary: '#d9a527',
10 | },
11 | },
12 | },
13 | plugins: [],
14 | }
15 |
--------------------------------------------------------------------------------