├── src ├── components │ ├── Designs.css │ ├── Details.css │ ├── Activities2.css │ ├── Designs.js │ ├── Details.js │ ├── Activities2.js │ ├── About.js │ ├── Navbar.js │ ├── Footer.js │ ├── About.css │ ├── Navbar.css │ ├── Footer.css │ ├── Contact.css │ ├── Contact.js │ ├── Activities.css │ └── Activities.js ├── assets │ └── file.jpg ├── setupTests.js ├── App.test.js ├── routes │ ├── About.js │ ├── Contact.js │ ├── Designs.js │ ├── Activities.js │ └── Home.js ├── reportWebVitals.js ├── index.js ├── App.js └── index.css ├── .gitignore ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── images │ └── heroBg.jpg ├── manifest.json └── index.html ├── server ├── package.json └── index.js ├── package.json ├── LICENSE └── README.md /src/components/Designs.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build -------------------------------------------------------------------------------- /src/components/Details.css: -------------------------------------------------------------------------------- 1 | .details { 2 | background-color: red; 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Activities2.css: -------------------------------------------------------------------------------- 1 | .activities2 { 2 | background-color: olive; 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZEviod/open-source-mern/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZEviod/open-source-mern/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZEviod/open-source-mern/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/assets/file.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZEviod/open-source-mern/HEAD/src/assets/file.jpg -------------------------------------------------------------------------------- /public/images/heroBg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ZEviod/open-source-mern/HEAD/public/images/heroBg.jpg -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/components/Designs.js: -------------------------------------------------------------------------------- 1 | import "./Designs.css"; 2 | import React from "react"; 3 | 4 | const Designs = () => { 5 | return ( 6 |
7 |

I am design

8 |
9 | ); 10 | }; 11 | 12 | export default Designs; 13 | -------------------------------------------------------------------------------- /src/components/Details.js: -------------------------------------------------------------------------------- 1 | import "./Details.css"; 2 | import React from "react"; 3 | 4 | const Details = () => { 5 | return ( 6 |
7 |

I am Details

8 |
9 | ); 10 | }; 11 | 12 | export default Details; 13 | -------------------------------------------------------------------------------- /src/components/Activities2.js: -------------------------------------------------------------------------------- 1 | import "./Activities2.css"; 2 | import React from "react"; 3 | 4 | const Activities2 = () => { 5 | return ( 6 |
7 |

I am details of activities2

8 |
9 | ); 10 | }; 11 | 12 | export default Activities2; 13 | -------------------------------------------------------------------------------- /src/routes/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../components/Navbar"; 3 | import Details from "../components/Details"; 4 | import Footer from "../components/Footer"; 5 | 6 | const Home = () => { 7 | return ( 8 |
9 | 10 |
11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Home; 17 | -------------------------------------------------------------------------------- /src/routes/Contact.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../components/Navbar"; 3 | import Contact from "../components/Contact"; 4 | import Footer from "../components/Footer"; 5 | 6 | const Home = () => { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Home; 17 | -------------------------------------------------------------------------------- /src/routes/Designs.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../components/Navbar"; 3 | import Designs from "../components/Designs"; 4 | import Footer from "../components/Footer"; 5 | 6 | const Home = () => { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Home; 17 | -------------------------------------------------------------------------------- /src/routes/Activities.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../components/Navbar"; 3 | import Activities2 from "../components/Activities2"; 4 | import Footer from "../components/Footer"; 5 | 6 | const Home = () => { 7 | return ( 8 |
9 | 10 | 11 |
12 |
13 | ); 14 | }; 15 | 16 | export default Home; 17 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-source-mern-server", 3 | "version": "0.1.0", 4 | "private": true, 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js", 8 | "dev": "nodemon index.js" 9 | }, 10 | "dependencies": { 11 | "cors": "^2.8.5", 12 | "express": "^4.18.2", 13 | "morgan": "^1.10.0", 14 | "nodemon": "^2.0.22", 15 | "express-validator": "^6.15.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/routes/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Navbar from "../components/Navbar"; 3 | import About from "../components/About"; 4 | import Footer from "../components/Footer"; 5 | import Activities from "../components/Activities"; 6 | 7 | const Home = () => { 8 | return ( 9 |
10 | 11 | 12 | 13 |
14 |
15 | ); 16 | }; 17 | 18 | export default Home; 19 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/components/About.js: -------------------------------------------------------------------------------- 1 | import "./About.css"; 2 | import React from "react"; 3 | 4 | const About = () => { 5 | return ( 6 |
7 |
8 |
9 |

ABOUT US

10 |

11 | Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque quae 12 | reiciendis eius et libero harum aliquid voluptatibus cum nihil 13 | tenetur molestias numquam perspiciatis, pariatur placeat corrupti 14 | beatae consequatur ducimus odit laborum laudantium, quis quia. 15 |

16 |
17 | 18 | 21 |
22 |
23 | ); 24 | }; 25 | 26 | export default About; 27 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./index.css"; 3 | import Home from "./routes/Home"; 4 | import About from "./routes/About"; 5 | import Contact from "./routes/Contact"; 6 | import Designs from "./routes/Designs"; 7 | import Activities from "./routes/Activities"; 8 | import { BrowserRouter, Route, Routes } from "react-router-dom"; 9 | 10 | function App() { 11 | return ( 12 | <> 13 | 14 | 15 | } /> 16 | } /> 17 | } /> 18 | } /> 19 | } /> 20 | 21 | 22 | 23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | /* Accessibility: visible focus styles for keyboard users */ 16 | :focus { 17 | outline: 3px solid #0b5fff; 18 | outline-offset: 2px; 19 | } 20 | 21 | /* Make focus more subtle for mouse users by removing when using pointer */ 22 | @media (pointer: fine) { 23 | :focus:not(:focus-visible) { 24 | outline: none; 25 | } 26 | } 27 | 28 | /* Screen-reader only utility */ 29 | .sr-only { 30 | position: absolute !important; 31 | height: 1px; 32 | width: 1px; 33 | overflow: hidden; 34 | clip: rect(1px, 1px, 1px, 1px); 35 | white-space: nowrap; 36 | border: 0; 37 | padding: 0; 38 | margin: -1px; 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-source-mern", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.17.0", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.3.1", 10 | "react-dom": "^18.3.1", 11 | "react-icons": "^5.3.0", 12 | "react-router-dom": "^6.27.0", 13 | "react-scripts": "5.0.1", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "proxy": "http://localhost:5000", 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Vivek Poonia 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/components/Navbar.js: -------------------------------------------------------------------------------- 1 | import "./Navbar.css"; 2 | import { useState } from "react"; 3 | import React from "react"; 4 | import { Link, NavLink } from "react-router-dom"; 5 | import { FaBars, FaTimes } from "react-icons/fa"; 6 | 7 | const navLinks = [ 8 | { to: "/", text: "Home" }, 9 | { to: "/about", text: "About" }, 10 | { to: "/designs", text: "Design" }, 11 | { to: "/activities", text: "Activity" }, 12 | ]; 13 | 14 | const Navbar = () => { 15 | const [isMenuOpen, setIsMenuOpen] = useState(false); 16 | 17 | const toggleMenu = () => setIsMenuOpen(!isMenuOpen); 18 | const closeMobileMenu = () => setIsMenuOpen(false); 19 | 20 | return ( 21 |
22 | 23 |

Working Studios

24 | 25 | 26 | 29 | 30 | 51 |
52 | ); 53 | }; 54 | 55 | export default Navbar; -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const express = require("express"); 2 | const fs = require("fs"); 3 | const path = require("path"); 4 | const morgan = require("morgan"); 5 | const cors = require("cors"); 6 | const { body, validationResult } = require("express-validator"); 7 | 8 | const app = express(); 9 | const PORT = process.env.PORT || 5000; 10 | 11 | app.use(morgan("dev")); 12 | app.use(cors()); 13 | app.use(express.json()); 14 | 15 | const messagesFile = path.join(__dirname, "messages.log"); 16 | 17 | // Ensure messages file exists 18 | try { 19 | fs.closeSync(fs.openSync(messagesFile, "a")); 20 | } catch (err) { 21 | console.error("Could not create messages.log", err); 22 | } 23 | 24 | app.post( 25 | "/api/contact", 26 | [ 27 | body("fullName") 28 | .trim() 29 | .isLength({ min: 2 }) 30 | .withMessage("Full name required"), 31 | body("email").isEmail().withMessage("Valid email required"), 32 | body("message") 33 | .trim() 34 | .isLength({ min: 5 }) 35 | .withMessage("Message too short"), 36 | ], 37 | (req, res) => { 38 | const errors = validationResult(req); 39 | if (!errors.isEmpty()) { 40 | return res.status(400).json({ errors: errors.array() }); 41 | } 42 | 43 | const { fullName, email, message } = req.body; 44 | const entry = { 45 | time: new Date().toISOString(), 46 | fullName, 47 | email, 48 | message, 49 | }; 50 | 51 | // Append to log file (simulate saving / sending email) 52 | fs.appendFile(messagesFile, JSON.stringify(entry) + "\n", (err) => { 53 | if (err) { 54 | console.error("Failed to write message", err); 55 | return res.status(500).json({ error: "Failed to save message" }); 56 | } 57 | // Respond success 58 | return res 59 | .status(201) 60 | .json({ status: "ok", message: "Message received" }); 61 | }); 62 | } 63 | ); 64 | 65 | app.get("/api/health", (req, res) => { 66 | res.json({ status: "ok" }); 67 | }); 68 | 69 | app.listen(PORT, () => { 70 | console.log(`Server listening on http://localhost:${PORT}`); 71 | }); 72 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | 26 | 27 | 28 | Working Studios 29 | 30 | 31 | 32 | 33 |
34 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | import "./Footer.css"; 2 | import React from "react"; 3 | import { Link } from "react-router-dom"; 4 | import { FaInstagram, FaFacebook, FaTwitter } from "react-icons/fa"; 5 | 6 | const Footer = () => { 7 | return ( 8 | 98 | ); 99 | }; 100 | 101 | export default Footer; 102 | -------------------------------------------------------------------------------- /src/components/About.css: -------------------------------------------------------------------------------- 1 | 2 | /* General Body and Font Styles */ 3 | body { 4 | background-color: #fffdd0; 5 | margin: 0; 6 | font-family: "Poppins", serif; 7 | } 8 | 9 | /* --- About Section --- */ 10 | .about { 11 | /* Using dvh unit for better mobile viewport handling */ 12 | height: calc(100dvh - 72px); 13 | width: 100%; 14 | background: linear-gradient( 15 | rgba(0, 0, 0, 0.65), 16 | rgba(0, 0, 0, 0.3) 17 | ), 18 | url(../../public/images/heroBg.jpg); 19 | background-repeat: no-repeat; 20 | background-size: cover; 21 | background-position: center; 22 | display: flex; 23 | align-items: center; 24 | justify-content: center; 25 | } 26 | 27 | /* Container */ 28 | .container { 29 | display: flex; 30 | flex-direction: column; 31 | align-items: center; 32 | justify-content: center; 33 | width: 90%; 34 | max-width: 800px; 35 | margin-inline: auto; 36 | height: 100%; 37 | gap: 2rem; 38 | padding: 1rem; 39 | } 40 | 41 | /* --- IMPROVEMENT: Glassmorphism Effect on Text Block --- */ 42 | .text { 43 | display: flex; 44 | flex-direction: column; 45 | align-items: center; 46 | justify-content: center; 47 | transition: transform 0.3s ease-in-out, box-shadow 0.3s ease-in-out; 48 | padding: 1.5rem; 49 | border-radius: 16px; /* Slightly increased for a softer look */ 50 | 51 | /* Added for the glass effect */ 52 | background: rgba(255, 255, 255, 0.1); /* Semi-transparent background */ 53 | backdrop-filter: blur(8px); /* The blur effect! */ 54 | -webkit-backdrop-filter: blur(8px); /* For Safari compatibility */ 55 | border: 1px solid rgba(255, 255, 255, 0.2); /* Subtle edge highlight */ 56 | box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); /* Soft shadow for depth */ 57 | } 58 | 59 | .text h1, 60 | .text p { 61 | font-family: "Poppins", serif; 62 | color: #fff; 63 | text-align: center; 64 | /* Add a subtle text shadow for better readability on the blurred background */ 65 | text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5); 66 | } 67 | 68 | .text h1 { 69 | font-size: 2rem; 70 | margin-bottom: 1rem; 71 | letter-spacing: 1px; 72 | } 73 | 74 | .text p { 75 | font-size: 1.1rem; 76 | line-height: 1.8rem; 77 | opacity: 0.95; 78 | } 79 | 80 | /* --- Button Styling --- */ 81 | /* Note: The first, duplicate .nav_links1 block was removed */ 82 | .nav_links1 { 83 | list-style: none; 84 | background-color: rgb(223, 163, 84); 85 | padding: 12px 24px; 86 | border-radius: 6px; 87 | color: #fff; 88 | font-weight: 500; 89 | outline: none; 90 | border: none; 91 | font-size: 1.05rem; 92 | font-family: "Poppins", serif; 93 | transition: all 0.3s ease; 94 | margin-top: 1rem; 95 | cursor: pointer; /* Added for better UX */ 96 | } 97 | 98 | .nav_links1:hover { 99 | background-color: rgb(223, 172, 106); 100 | transform: translateY(-3px); 101 | box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25); 102 | } 103 | 104 | .button-50 { 105 | background-color: rgb(0, 0, 0); 106 | box-sizing: border-box; 107 | color: #fff; 108 | cursor: pointer; 109 | font-size: 24px; 110 | text-align: center; 111 | vertical-align: middle; 112 | padding: 12px 20px; 113 | border: none; 114 | border-radius: 6px; 115 | transition: all 0.4s ease; 116 | } 117 | 118 | .button-50:hover { 119 | background-color: #aaaaaa; 120 | color: #000; 121 | border-radius: 8px; 122 | transform: translateY(-3px); 123 | box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2); 124 | } 125 | 126 | /* --- Responsive Styling --- */ 127 | @media screen and (min-width: 640px) { 128 | .container { 129 | width: 80%; /* Adjusted for better spacing with the new text box */ 130 | max-width: 700px; 131 | } 132 | .text h1 { 133 | font-size: 2.5rem; 134 | } 135 | .text p { 136 | font-size: 1.2rem; 137 | line-height: 2rem; 138 | } 139 | } -------------------------------------------------------------------------------- /src/components/Navbar.css: -------------------------------------------------------------------------------- 1 | 2 | @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400..900;1,400..900&display=swap'); 3 | 4 | :root { 5 | --bg-primary: bisque; 6 | --bg-hover: #e6c97d; 7 | --cta-bg: rgb(223, 163, 84); 8 | --cta-bg-hover: rgb(223, 172, 106); 9 | --text-primary: brown; 10 | --text-secondary: black; 11 | --text-cta: #eee; 12 | --font-body: "Poppins", sans-serif; 13 | --nav-height: 72px; 14 | --border-subtle: #d3b8a0; 15 | --font-brand: "Playfair Display", serif; 16 | } 17 | 18 | *, *::before, *::after { 19 | box-sizing: border-box; 20 | margin: 0; 21 | padding: 0; 22 | } 23 | 24 | body { 25 | font-family: var(--font-body); 26 | } 27 | 28 | .navbar { 29 | display: flex; 30 | justify-content: space-between; 31 | align-items: center; 32 | height: var(--nav-height); 33 | padding-inline: 24px; 34 | background-color: var(--bg-primary); 35 | position: relative; 36 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); 37 | } 38 | 39 | .navbar__brand-name { 40 | font-family: var(--font-brand); 41 | font-size: 28px; 42 | font-weight: 700; 43 | color: var(--text-secondary); 44 | text-decoration: none; 45 | line-height: 1; 46 | } 47 | 48 | .navbar__menu { 49 | position: absolute; 50 | top: var(--nav-height); 51 | left: 0; 52 | right: 0; 53 | background-color: var(--bg-primary); 54 | display: flex; 55 | flex-direction: column; 56 | align-items: center; 57 | gap: 1.5rem; 58 | padding: 2rem 0; 59 | border-bottom: 1px solid var(--border-subtle); 60 | 61 | /* Animation properties for a smooth slide-down effect */ 62 | transform: translateY(-100%); 63 | opacity: 0; 64 | visibility: hidden; 65 | transition: transform 0.3s ease-out, opacity 0.3s ease-out, visibility 0.3s ease-out; 66 | z-index: 99; 67 | } 68 | 69 | .navbar__menu.is-active { 70 | transform: translateY(0); 71 | opacity: 1; 72 | visibility: visible; 73 | } 74 | 75 | .navbar__links { 76 | list-style: none; 77 | display: flex; 78 | flex-direction: column; /* Stacks links vertically on mobile */ 79 | align-items: center; 80 | gap: 1.5rem; 81 | } 82 | 83 | /* 5. Combined Styling for Navigation Links and the CTA Button */ 84 | .navbar__link { 85 | font-size: 18px; 86 | font-weight: 500; 87 | color: var(--text-primary); 88 | text-decoration: none; 89 | padding: 8px 12px; 90 | border-radius: 4px; 91 | transition: all 0.3s ease; 92 | } 93 | 94 | .navbar__link:hover { 95 | color: var(--text-secondary); 96 | background-color: var(--bg-hover); 97 | } 98 | 99 | /* This style is automatically applied by React Router's */ 100 | .navbar__link.active { 101 | font-weight: 700; 102 | color: var(--text-secondary); 103 | } 104 | 105 | .navbar__cta { 106 | font-size: 18px; 107 | font-weight: 500; 108 | color: var(--text-cta); 109 | text-decoration: none; 110 | background-color: var(--cta-bg); 111 | padding: 10px 16px; 112 | border-radius: 4px; 113 | transition: background-color 0.3s ease; 114 | } 115 | 116 | .navbar__cta:hover { 117 | background-color: var(--cta-bg-hover); 118 | } 119 | 120 | /* 6. Hamburger Icon Styling */ 121 | .navbar__hamburger { 122 | display: flex; /* Or block */ 123 | background: none; 124 | border: none; 125 | color: var(--text-primary); 126 | cursor: pointer; 127 | z-index: 100; /* Ensures it's above other content */ 128 | } 129 | 130 | /* 7. Desktop styles - This is where the magic happens for responsiveness */ 131 | @media screen and (min-width: 768px) { 132 | .navbar__hamburger { 133 | display: none; 134 | } 135 | 136 | .navbar__menu { 137 | /* Reset all the mobile-specific positioning and styling */ 138 | position: static; 139 | transform: none; 140 | opacity: 1; 141 | visibility: visible; 142 | flex-direction: row; 143 | align-items: center; 144 | gap: 2rem; 145 | padding: 0; 146 | background-color: transparent; 147 | border-bottom: none; 148 | } 149 | 150 | .navbar__links { 151 | flex-direction: row; 152 | gap: 2vw; /* Use vw for flexible spacing on different desktop screen sizes */ 153 | } 154 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # open-source-mern 2 | 3 | # Getting Started with Create React App 4 | 5 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 6 | 7 | ## Available Scripts 8 | 9 | In the project directory, you can run: 10 | 11 | ### Server (contact API) 12 | 13 | This project includes a small Express server under the `server/` folder that provides a POST `/api/contact` endpoint for the contact form. 14 | 15 | To run the server (requires Node.js): 16 | 17 | ```powershell 18 | cd server 19 | npm install 20 | npm run start 21 | ``` 22 | 23 | The client (React app) is configured with a `proxy` in `package.json` so requests to `/api/contact` from the development server will be forwarded to `http://localhost:5000` where the Express server listens. 24 | 25 | Messages submitted to `/api/contact` are validated server-side and appended to `server/messages.log` to simulate persistence or sending an email. 26 | 27 | ### `npm start` 28 | 29 | Runs the app in the development mode.\ 30 | Open [http://localhost:3000](http://localhost:3000) to view it in your browser. 31 | 32 | The page will reload when you make changes.\ 33 | You may also see any lint errors in the console. 34 | 35 | ### `npm test` 36 | 37 | Launches the test runner in the interactive watch mode.\ 38 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 39 | 40 | ### `npm run build` 41 | 42 | Builds the app for production to the `build` folder.\ 43 | It correctly bundles React in production mode and optimizes the build for the best performance. 44 | 45 | The build is minified and the filenames include the hashes.\ 46 | Your app is ready to be deployed! 47 | 48 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 49 | 50 | ### `npm run eject` 51 | 52 | **Note: this is a one-way operation. Once you `eject`, you can't go back!** 53 | 54 | If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 55 | 56 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. 57 | 58 | You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. 59 | 60 | ## Learn More 61 | 62 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 63 | 64 | To learn React, check out the [React documentation](https://reactjs.org/). 65 | 66 | ### Code Splitting 67 | 68 | This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) 69 | 70 | ### Analyzing the Bundle Size 71 | 72 | This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) 73 | 74 | ### Making a Progressive Web App 75 | 76 | This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) 77 | 78 | ### Advanced Configuration 79 | 80 | This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) 81 | 82 | ### Deployment 83 | 84 | This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) 85 | 86 | ### `npm run build` fails to minify 87 | 88 | This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) 89 | -------------------------------------------------------------------------------- /src/components/Footer.css: -------------------------------------------------------------------------------- 1 | /* --- CSS Variables for Easy Theming --- */ 2 | :root { 3 | --footer-gradient: linear-gradient(to right, rgb(150, 106, 23), #fbcf6f); 4 | --footer-bg-hover: rgb(150, 106, 23); 5 | --footer-text-color: #fff; 6 | --footer-link-hover: #ffdead; /* A lighter, more complementary hover color */ 7 | --body-bg-color: #eef8ff; 8 | --font-primary: "Poppins", sans-serif; 9 | } 10 | 11 | /* --- Global Reset and Font Settings --- */ 12 | * { 13 | margin: 0; 14 | padding: 0; 15 | box-sizing: border-box; 16 | } 17 | 18 | body { 19 | background-color: var(--body-bg-color); 20 | font-family: var(--font-primary); 21 | } 22 | 23 | /* --- Footer Container --- */ 24 | .footer { 25 | width: 100%; 26 | background: var(--footer-gradient); 27 | color: var(--footer-text-color); 28 | /* IMPROVEMENT: Responsive padding */ 29 | padding: 60px clamp(1rem, 5vw, 4rem) 30px; 30 | /* IMPROVEMENT: A slightly more subtle border-radius */ 31 | border-top-left-radius: 65px; 32 | font-size: 14px; 33 | /* This pushes the footer down. Consider managing this space on the element above the footer. */ 34 | margin-top: 148px; 35 | } 36 | 37 | /* --- Footer Layout --- */ 38 | .footer-content { 39 | width: 100%; 40 | max-width: 1200px; /* Set a max-width for very large screens */ 41 | margin: auto; 42 | display: flex; 43 | flex-wrap: wrap; 44 | justify-content: space-between; 45 | /* IMPROVEMENT: Use gap for consistent spacing between columns */ 46 | gap: 2rem; 47 | } 48 | 49 | .footer-col { 50 | /* Each column will take up the full width on mobile */ 51 | flex-grow: 1; 52 | flex-basis: 100%; 53 | } 54 | 55 | /* --- Logo and Description --- */ 56 | .logo-footer { 57 | width: 180px; 58 | height: auto; 59 | margin-bottom: 1rem; 60 | } 61 | 62 | .footer-description { 63 | font-size: 1rem; 64 | line-height: 1.6; 65 | max-width: 350px; /* Prevents text from stretching too far */ 66 | } 67 | 68 | /* --- Social Media Icons --- */ 69 | .social-icons { 70 | margin-top: 1.5rem; 71 | display: flex; /* Use flex to align icons */ 72 | gap: 10px; 73 | } 74 | 75 | .social-icons a { 76 | /* IMPROVEMENT: Use flexbox for perfect centering */ 77 | display: flex; 78 | align-items: center; 79 | justify-content: center; 80 | width: 35px; 81 | height: 35px; 82 | border-radius: 50%; 83 | color: #000; 84 | background: #fff; 85 | text-decoration: none; 86 | transition: all 0.3s ease; 87 | } 88 | 89 | .social-icons a:hover { 90 | color: #fff; 91 | background: var(--footer-bg-hover); 92 | transform: translateY(-3px); /* Add a subtle lift effect */ 93 | } 94 | 95 | /* --- Section Headings --- */ 96 | .footer-col h3 { 97 | font-size: 1.1rem; 98 | font-weight: 600; 99 | margin-bottom: 1.5rem; 100 | position: relative; 101 | } 102 | 103 | /* --- Links and Contact Info --- */ 104 | .footer-links { 105 | list-style: none; 106 | } 107 | 108 | .footer-links li { 109 | margin-bottom: 12px; 110 | } 111 | 112 | .footer-links a, 113 | .contact-col p a { 114 | text-decoration: none; 115 | color: var(--footer-text-color); 116 | transition: color 0.3s ease; 117 | } 118 | 119 | .footer-links a:hover, 120 | .contact-col p a:hover { 121 | color: var(--footer-link-hover); 122 | padding-left: 5px; /* Nudge text on hover */ 123 | } 124 | 125 | .email-id { 126 | display: inline-block; 127 | border-bottom: 1px solid rgba(255, 255, 255, 0.5); 128 | margin-top: 10px; 129 | } 130 | 131 | /* --- Map --- */ 132 | .location-map { 133 | width: 100%; 134 | height: 200px; 135 | border: 0; 136 | border-radius: 8px; /* Give the map rounded corners */ 137 | margin-top: 10px; 138 | } 139 | 140 | 141 | /* --- RESPONSIVE STYLES --- */ 142 | 143 | /* For Small Tablets */ 144 | @media screen and (min-width: 624px) { 145 | .footer-col { 146 | /* Creates a two-column layout */ 147 | flex-basis: 45%; 148 | } 149 | } 150 | 151 | /* For Desktops and Larger Tablets */ 152 | @media screen and (min-width: 992px) { 153 | .footer-col { 154 | /* Creates a four-column layout */ 155 | flex-basis: 22%; 156 | } 157 | } -------------------------------------------------------------------------------- /src/components/Contact.css: -------------------------------------------------------------------------------- 1 | /* --- CSS Variables for Easy Theming --- */ 2 | :root { 3 | --bg-color: #e9d8fd; 4 | --card-bg-color: #ffffff; 5 | --primary-blue: #3b82f6; 6 | --primary-blue-hover: #2563eb; 7 | --text-color-primary: #1e293b; 8 | --text-color-secondary: #64748b; 9 | --border-color: #e5e7eb; 10 | --focus-color: #a5b4fc; 11 | } 12 | 13 | /* --- Main Container --- */ 14 | .contact-container { 15 | min-height: 80vh; 16 | background-color: var(--bg-color); 17 | /* IMPROVEMENT: Responsive padding for better spacing on all screen sizes */ 18 | padding: clamp(1.5rem, 5vw, 3rem); 19 | font-family: sans-serif; /* Added a default font family */ 20 | } 21 | 22 | /* --- Layout --- */ 23 | .contact-content { 24 | display: flex; 25 | justify-content: space-between; 26 | /* IMPROVEMENT: Added a gap for spacing between columns */ 27 | gap: 2rem; 28 | } 29 | 30 | /* --- Left Side: Contact Info --- */ 31 | .contact-info { 32 | width: 50%; 33 | padding-right: 2rem; /* Spacing from the form */ 34 | } 35 | 36 | .contact-title { 37 | font-size: 4rem; 38 | font-weight: 600; 39 | color: var(--text-color-primary); 40 | } 41 | 42 | .contact-description { 43 | /* IMPROVEMENT: Use max-width to allow shrinking on smaller screens */ 44 | max-width: 25rem; 45 | color: var(--text-color-secondary); 46 | margin-top: 1rem; 47 | line-height: 1.6; 48 | } 49 | 50 | .contact-email, 51 | .contact-phone { 52 | /* IMPROVEMENT: Added icons for better visual communication */ 53 | display: flex; 54 | align-items: center; 55 | gap: 0.75rem; 56 | margin: 1.5rem 0; 57 | color: var(--text-color-secondary); 58 | } 59 | 60 | .support-sections { 61 | margin-top: 3rem; 62 | display: flex; 63 | flex-wrap: wrap; 64 | gap: 2.5rem; 65 | } 66 | 67 | .support-item { 68 | width: 15rem; 69 | } 70 | 71 | .support-title { 72 | font-weight: 600; 73 | font-size: 1.2rem; 74 | color: var(--text-color-primary); 75 | } 76 | 77 | .support-text { 78 | font-size: 0.9rem; 79 | color: var(--text-color-secondary); 80 | line-height: 1.5; 81 | } 82 | 83 | /* --- Right Side: Contact Form --- */ 84 | .contact-form { 85 | width: 50%; 86 | padding: 2.5rem; /* Increased padding for a more spacious feel */ 87 | background-color: var(--card-bg-color); 88 | border-radius: 1rem; 89 | /* IMPROVEMENT: Added a subtle shadow to lift the form off the page */ 90 | box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); 91 | } 92 | 93 | .form-title { 94 | font-size: 2.3rem; 95 | font-weight: 600; 96 | color: var(--text-color-primary); 97 | } 98 | 99 | .form-subtitle { 100 | color: var(--text-color-secondary); 101 | margin-bottom: 2rem; 102 | } 103 | 104 | .form-fields { 105 | display: flex; 106 | flex-direction: column; 107 | gap: 1.5rem; /* Increased gap for better separation */ 108 | } 109 | 110 | .input, 111 | .textarea { 112 | width: 100%; 113 | padding: 0.75rem 1rem; 114 | border: 1px solid var(--border-color); /* Softened the border */ 115 | border-radius: 0.5rem; /* A more standard, modern border-radius */ 116 | transition: border-color 0.3s, box-shadow 0.3s; /* Smooth focus transition */ 117 | } 118 | 119 | .input:focus, 120 | .textarea:focus { 121 | outline: none; 122 | border-color: var(--focus-color); 123 | box-shadow: 0 0 0 3px rgba(165, 180, 252, 0.5); /* A modern focus ring */ 124 | } 125 | 126 | .textarea { 127 | min-height: 120px; /* Set a minimum height */ 128 | resize: vertical; /* Allow vertical resizing */ 129 | } 130 | 131 | .submit-button { 132 | width: 100%; 133 | padding: 1rem; 134 | border-radius: 0.5rem; 135 | background-color: var(--primary-blue); 136 | color: white; 137 | font-weight: 600; 138 | font-size: 1.125rem; 139 | border: none; 140 | cursor: pointer; 141 | transition: background-color 0.3s; 142 | } 143 | 144 | .submit-button:hover { 145 | background-color: var(--primary-blue-hover); 146 | } 147 | 148 | /* --- Form Status Messages --- */ 149 | .form-error, .form-success, .form-sending { 150 | padding: 0.75rem 1rem; 151 | border-radius: 0.5rem; 152 | margin-top: 1rem; 153 | text-align: center; 154 | } 155 | .form-error { color: #b91c1c; background: #fee2e2; } 156 | .form-success { color: #065f46; background: #d1fae5; } 157 | .form-sending { color: #1e293b; background: #f1f5f9; } 158 | 159 | 160 | /* --- RESPONSIVE STYLES --- */ 161 | @media screen and (max-width: 992px) { 162 | .contact-content { 163 | /* Stacks the columns on top of each other */ 164 | flex-direction: column; 165 | } 166 | 167 | .contact-info, 168 | .contact-form { 169 | /* Both sections take up the full width */ 170 | width: 100%; 171 | padding: 0; 172 | } 173 | 174 | .contact-form { 175 | padding: 2rem; /* Maintain padding on the form itself */ 176 | } 177 | 178 | .contact-title { 179 | font-size: 3rem; /* Reduce title size on smaller screens */ 180 | } 181 | 182 | .form-title { 183 | font-size: 2rem; 184 | } 185 | } -------------------------------------------------------------------------------- /src/components/Contact.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import "./Contact.css"; 3 | 4 | const Contact = () => { 5 | const [status, setStatus] = useState({ state: "idle", message: "" }); 6 | const [isSending, setIsSending] = useState(false); 7 | 8 | const handleSubmit = async (e) => { 9 | e.preventDefault(); 10 | const fullName = e.currentTarget.fullName.value.trim(); 11 | const email = e.currentTarget.email.value.trim(); 12 | const message = e.currentTarget.message.value.trim(); 13 | 14 | if (!fullName || fullName.length < 2) { 15 | setStatus({ state: "error", message: "Please enter your full name." }); 16 | return; 17 | } 18 | if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { 19 | setStatus({ 20 | state: "error", 21 | message: "Please enter a valid email address.", 22 | }); 23 | return; 24 | } 25 | if (!message || message.length < 5) { 26 | setStatus({ 27 | state: "error", 28 | message: "Message must be at least 5 characters.", 29 | }); 30 | return; 31 | } 32 | 33 | setIsSending(true); 34 | setStatus({ state: "sending", message: "Sending..." }); 35 | 36 | try { 37 | const resp = await fetch("/api/contact", { 38 | method: "POST", 39 | headers: { "Content-Type": "application/json" }, 40 | body: JSON.stringify({ fullName, email, message }), 41 | }); 42 | 43 | if (!resp.ok) { 44 | const data = await resp.json().catch(() => ({})); 45 | const errMsg = 46 | data && data.errors 47 | ? data.errors.map((e) => e.msg).join(", ") 48 | : data.error || "Failed to send message"; 49 | setStatus({ state: "error", message: errMsg }); 50 | setIsSending(false); 51 | return; 52 | } 53 | 54 | setStatus({ 55 | state: "success", 56 | message: "Thanks — your message has been sent.", 57 | }); 58 | e.currentTarget.reset(); 59 | } catch (err) { 60 | setStatus({ 61 | state: "error", 62 | message: "Network error — please try again later.", 63 | }); 64 | } finally { 65 | setIsSending(false); 66 | } 67 | }; 68 | 69 | return ( 70 |
71 |
72 |
73 |

74 | Contact Us 75 |

76 |

77 | Email, call, or complete the form to learn how Personal Finance 78 | Tracker can solve your messaging problem. 79 |

80 |

81 | hello@OpenSourceMern.in 82 |

83 |

84 | 123-345-567 85 |

86 | 87 |
91 |

92 | Customer Support 93 |

94 |
95 |

Customer Support

96 |

97 | Our support team is available around the clock to address any 98 | concerns or queries you may have. 99 |

100 |
101 |
102 |

Feedback and Suggestions

103 |

104 | We value your feedback and are continuously working to improve 105 | OSM. Your input is crucial in shaping the future of Us. 106 |

107 |
108 |
109 |

Finance Inquiries

110 |

111 | For Finance-related questions or any help, please contact us at 112 | Finance@OpenSourceMern.in 113 |

114 |
115 |
116 |
117 | 118 |
119 |
124 |
125 |

Get in Touch

126 |

You can reach us anytime

127 |
128 | 129 |
130 |
131 | 132 | 140 |
141 | 142 |
143 | 144 | 152 |
153 | 154 |
155 | 156 | 164 |
165 | 166 | 174 | 175 |
176 | {status.state === "error" && ( 177 |

178 | {status.message} 179 |

180 | )} 181 | {status.state === "success" && ( 182 |

{status.message}

183 | )} 184 | {status.state === "sending" && ( 185 |

{status.message}

186 | )} 187 |
188 |
189 |
190 |
191 |
192 |
193 | ); 194 | }; 195 | 196 | export default Contact; 197 | -------------------------------------------------------------------------------- /src/components/Activities.css: -------------------------------------------------------------------------------- 1 | .activities{ 2 | padding-top: 48px; 3 | background-color: #e6c97d rgba(255, 255, 255, 1); 4 | padding-inline: 24px; 5 | } 6 | .activities h1{ 7 | text-align: center; 8 | font-family: "Poppins", serif; 9 | font-style: normal; 10 | font-weight: 600; 11 | color: #ff9966; 12 | text-transform: capitalize; 13 | font-size: 2.2rem; 14 | } 15 | .newFex { 16 | display: flex; 17 | flex-direction: row; 18 | justify-content: center; 19 | flex-wrap: wrap; 20 | gap: 100px; 21 | padding-top: 50px; 22 | } 23 | 24 | .back_img { 25 | width: 15%; 26 | border-style: solid; 27 | border-color: #ff9966; 28 | border-radius: 5px; 29 | } 30 | .front_img { 31 | width: 100%; 32 | height: 100%; 33 | border-style: solid; 34 | border-color: #ff9966; 35 | border-radius: 5px; 36 | } 37 | .card { 38 | overflow: visible; 39 | width: 525px; 40 | height: 400px; 41 | } 42 | 43 | .content { 44 | width: 100%; 45 | height: 100%; 46 | transform-style: preserve-3d; 47 | transition: transform 300ms; 48 | box-shadow: 0px 0px 10px 1px #000000ee; 49 | border-radius: 5px; 50 | } 51 | 52 | .front, 53 | .back { 54 | background-color: #151515; 55 | position: absolute; 56 | width: 100%; 57 | height: 100%; 58 | backface-visibility: hidden; 59 | -webkit-backface-visibility: hidden; 60 | border-radius: 5px; 61 | overflow: hidden; 62 | } 63 | 64 | .back { 65 | width: 100%; 66 | height: 100%; 67 | justify-content: center; 68 | display: flex; 69 | align-items: center; 70 | overflow: hidden; 71 | } 72 | 73 | .back::before { 74 | position: absolute; 75 | content: " "; 76 | display: block; 77 | width: 160px; 78 | height: 160%; 79 | background: linear-gradient( 80 | 90deg, 81 | transparent, 82 | #ff9966, 83 | #ff9966, 84 | #ff9966, 85 | #ff9966, 86 | transparent 87 | ); 88 | animation: rotation_481 5000ms infinite linear; 89 | } 90 | 91 | .back-content { 92 | position: absolute; 93 | width: 99%; 94 | height: 99%; 95 | background-color: #151515; 96 | border-radius: 5px; 97 | color: white; 98 | display: flex; 99 | flex-direction: column; 100 | justify-content: center; 101 | align-items: center; 102 | gap: 30px; 103 | } 104 | 105 | .card:hover .content { 106 | transform: rotateY(180deg); 107 | } 108 | 109 | @keyframes rotation_481 { 110 | 0% { 111 | transform: rotateZ(0deg); 112 | } 113 | 114 | 0% { 115 | transform: rotateZ(360deg); 116 | } 117 | } 118 | 119 | .front { 120 | transform: rotateY(180deg); 121 | color: white; 122 | } 123 | 124 | .front .front-content { 125 | position: absolute; 126 | width: 100%; 127 | height: 100%; 128 | padding: 10px; 129 | display: flex; 130 | flex-direction: column; 131 | justify-content: space-between; 132 | } 133 | 134 | .front-content .badge { 135 | background-color: #00000055; 136 | padding: 2px 10px; 137 | border-radius: 10px; 138 | backdrop-filter: blur(2px); 139 | width: fit-content; 140 | } 141 | 142 | .description { 143 | box-shadow: 0px 0px 10px 5px #00000088; 144 | width: 100%; 145 | padding: 10px; 146 | background-color: #00000099; 147 | backdrop-filter: blur(5px); 148 | border-radius: 5px; 149 | } 150 | 151 | .title { 152 | font-size: 11px; 153 | max-width: 100%; 154 | display: flex; 155 | justify-content: space-between; 156 | } 157 | 158 | .title p { 159 | width: 50%; 160 | } 161 | 162 | .card-footer { 163 | color: #ffffff88; 164 | margin-top: 5px; 165 | font-size: 8px; 166 | } 167 | 168 | .front .img { 169 | position: absolute; 170 | width: 100%; 171 | height: 100%; 172 | object-fit: cover; 173 | object-position: center; 174 | } 175 | 176 | @keyframes floating { 177 | 0% { 178 | transform: translateY(0px); 179 | } 180 | 181 | 50% { 182 | transform: translateY(10px); 183 | } 184 | 185 | 100% { 186 | transform: translateY(0px); 187 | } 188 | } 189 | .card-container { 190 | max-width: 100vw; 191 | /* max-height: 25vh; */ 192 | margin: auto; 193 | padding-bottom: 64px; 194 | display: flex; 195 | flex-direction: row; 196 | gap: 2rem; 197 | justify-content: space-around; 198 | flex-wrap: wrap; 199 | width: 100%; 200 | } 201 | 202 | .client { 203 | text-align: center; 204 | margin-top: 148px; 205 | padding-top: 50px; 206 | background-color: #e6c97d; 207 | position: relative; 208 | width: 100%; 209 | } 210 | .client-gradient{ 211 | position: absolute; 212 | top: -100px; 213 | width: 100%; 214 | height: 100px; 215 | } 216 | .client-gradient-second{ 217 | position: absolute; 218 | 219 | width: 100%; 220 | height: 100px; 221 | transform: rotate(180deg); 222 | bottom: -100px; 223 | } 224 | .client-gradient svg, 225 | .client-gradient-second svg{ 226 | height: 100px; 227 | width: 100%; 228 | } 229 | .client_card { 230 | background-color: rgb(255, 255, 255); 231 | color: #000; 232 | text-align: center; 233 | padding-inline: 24px; 234 | padding-top: 48px; 235 | padding-bottom: 16px; 236 | margin-top: 4%; 237 | border-radius: 8px; 238 | box-shadow: 10px 10px 32px #dedede; 239 | width: 380px; 240 | transition: transform 0.4s ease, box-shadow 0.4s ease; 241 | } 242 | 243 | .client_card > p, 244 | .client_content > p { 245 | font-family: "Poppins", serif; 246 | font-size: 14px; 247 | opacity: 0.9; 248 | } 249 | 250 | .client_card:hover { 251 | cursor: pointer; 252 | transform: translateY(-20px); 253 | box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); 254 | } 255 | 256 | 257 | 258 | .client h1 { 259 | text-align: center; 260 | font-family: "Poppins", serif; 261 | font-style: normal; 262 | font-weight: 600; 263 | color: white; 264 | text-transform: capitalize; 265 | font-size: 2.2rem; 266 | } 267 | 268 | .para_gap1 { 269 | margin-bottom: 5px; 270 | } 271 | .client_content{ 272 | display: flex; 273 | align-items: center; 274 | justify-content: space-between; 275 | width: 100%; 276 | margin-top: 1rem; 277 | } 278 | .para_gap2 { 279 | margin-bottom: 30px; 280 | } 281 | 282 | .para_gap3 { 283 | margin-bottom: 2px; 284 | } 285 | 286 | .bar { 287 | border-bottom: 1.5px solid #49a078; 288 | width: 15%; 289 | margin: auto; 290 | margin-top: 20px; 291 | display: block; 292 | } 293 | 294 | .bar_cc { 295 | border-bottom: 1px solid #03630e; 296 | width: 20%; 297 | margin-top: 25px; 298 | margin-bottom: 22px; 299 | margin-left: 40%; 300 | display: block; 301 | } 302 | 303 | .client_img { 304 | width: 64px; 305 | height: 64px; 306 | border-style: solid; 307 | border-color: #03630e; 308 | border-radius: 100px; 309 | } 310 | /* 311 | .client_img1 { 312 | width: 34%; 313 | } 314 | 315 | .client_img2 { 316 | width: 35%; 317 | } 318 | 319 | .client_img3 { 320 | width: 35%; 321 | } */ 322 | 323 | @media screen and (max-width: 930px) { 324 | .card-container { 325 | display: flex; 326 | flex-wrap: wrap; 327 | } 328 | .client_card { 329 | /* padding: 64px; */ 330 | 331 | } 332 | } 333 | 334 | @media screen and (max-width: 530px) { 335 | .card-container { 336 | flex-direction: column; 337 | justify-content: center; 338 | align-items: center; 339 | } 340 | 341 | .client_card { 342 | padding-inline: 24px; 343 | padding-block: 48px; 344 | max-width: 90vw; 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /src/components/Activities.js: -------------------------------------------------------------------------------- 1 | import "./Activities.css"; 2 | import React from "react"; 3 | import { FaQuoteLeft } from "react-icons/fa"; 4 | import img1 from "../assets/file.jpg"; 5 | 6 | const Activities = () => { 7 | return ( 8 | <> 9 |
10 |

Activities

11 | 12 |
13 |
14 |
15 |
16 |
17 | Back view of ceramic artwork 23 | Hover Me 24 |
25 |
26 |
31 |
32 | Front view of ceramic artwork 38 |
39 | 40 |
41 | Design 42 |
43 |
44 |

45 | Artist 46 |

47 | 54 | 70 | 71 | 72 | 73 | 74 | 75 |
76 |

art   |   1 piece

77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | Back view of ceramic artwork 92 | Hover Me 93 |
94 |
95 |
96 | Front view of ceramic artwork 102 | 103 |
104 | Design 105 |
106 |
107 |

108 | Artist 109 |

110 | 117 | 133 | 134 | 135 | 136 | 137 | 138 |
139 |

art   |   1 piece

140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 | Back view of ceramic artwork 155 | Hover Me 156 |
157 |
158 |
159 | Front view of ceramic artwork 165 | 166 |
167 | Design 168 |
169 |
170 |

171 | Artist 172 |

173 | 180 | 196 | 197 | 198 | 199 | 200 | 201 |
202 |

art   |   1 piece

203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | Back view of ceramic artwork 218 | Hover Me 219 |
220 |
221 |
222 | Front view of ceramic artwork 228 | 229 |
230 | Design 231 |
232 |
233 |

234 | Artist 235 |

236 | 243 | 259 | 260 | 261 | 262 | 263 | 264 |
265 |

art   |   1 piece

266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 | 280 | 281 | 282 | 290 | 291 | 292 | 293 | 294 | 295 |
296 |

What My Clients Say

297 | 298 |
299 |
300 |
301 | 310 |
311 |

312 | The instructor was incredibly patient and skilled, guiding us 313 | through pottery techniques with ease. Loved the therapeutic aspect 314 | and left feeling accomplished! 315 |

316 | 317 |
318 | Portrait of client Mihir Bohra 324 |

Mihir Bohra

325 |
326 |
327 |
328 |
329 | 338 |
339 | 340 |

341 | Exceptional className! The instructor’s expertise was matched only 342 | by their encouragement. A perfect blend of learning and 343 | relaxation. 344 |

345 | 346 |
347 | Portrait of client Ashish Gandhi 353 |

Ashish Gandhi

354 |
355 |
356 |
357 |
358 | 367 |
368 |

369 | A wonderful creative escape! The className struck a balance 370 | between guidance and freedom. The studio had everything I needed, 371 | and the instructor's passion was contagious. 372 |

373 | 374 |
375 | Portrait of client Abhineet Dubey 381 |

Abhineet Dubey

382 |
383 |
384 |
385 |
386 | 391 | 392 | 393 | 401 | 402 | 403 | 404 | 405 | 406 |
407 |
408 | 409 | ); 410 | }; 411 | 412 | export default Activities; 413 | --------------------------------------------------------------------------------