From 73e8c0835efd66b2032e2e38352e645376435171 Mon Sep 17 00:00:00 2001 From: Abdullahi Abdulkadir Date: Thu, 24 Jul 2025 05:22:05 +0100 Subject: [PATCH 01/11] faq added --- README.md | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++- faq.md | 51 +++++++++++++++++++++ strent-app | 1 + 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 faq.md create mode 160000 strent-app diff --git a/README.md b/README.md index e4ac270..12facc5 100644 --- a/README.md +++ b/README.md @@ -1 +1,127 @@ -# frontend \ No newline at end of file +# frontend +# 🌟 Strent App + +A collaborative, responsive web project built with **React**, **Vite**, **Tailwind CSS**, and managed with **pnpm**. This app is designed for maintainability, reusability, and team collaboration as part of the AltSchool project initiative. + +--- + +## πŸ“Œ Overview + +Strent-App is a modern frontend project focused on clean UI, reusable components, and efficient state management. The goal is to demonstrate best practices while building a scalable, modular front-end application. + +--- + +## 🧰 Tech Stack to get start + +- βš›οΈ React +- ⚑ Vite (for fast bundling) +- πŸ’¨ Tailwind CSS +- 🧠 React Context API/Recoil +- 🧩 React Router DOM +- πŸ“¦ **pnpm** (package manager) + +--- + +## πŸš€ Getting Started + +### 1. Clone the Repository + +```bash +git clone https://github.com/your-username/strent-app.git +cd strent-app +## 2. Install Dependencies with pnpm +Make sure pnpm is installed globally: +npm install -g pnpm + +Then install dependencies: +pnpm install + +3. Run the Development Server +pnpm dev + + +Visit http://localhost:5173 in your browser. or on your terminal ctl + click + + + + +πŸ—‚οΈ Folder Structure + +src/ +β”‚ +β”œβ”€β”€ components/ # Shared reusable components (Navbar, Footer, etc.) +β”œβ”€β”€ pages/ # Page-specific views (Home, About, Contact) +β”œβ”€β”€ context/ # React Context for global state +β”œβ”€β”€ hooks/ # Custom React hooks +β”œβ”€β”€ utils/ # Utility/helper functions +β”œβ”€β”€ images/ # Static image in assets +β”œβ”€β”€ icons/ # Icon, SVGs in asset +β”œβ”€β”€ fonts/ # Web font files (optional) in asset +β”‚ +β”œβ”€β”€ App.jsx # Root component with routes +β”œβ”€β”€ main.jsx # Entry point of the app +└── index.css # Tailwind base styles + + +πŸ§ͺ Features +βš›οΈ Component think of it as if its use all around its a component (nav, footer, button ) + +πŸ” Pages think of it tied to route its a pages (home, contact, etc) + +🧠 Global State via Context or recoil + +πŸ“± Mobile-First Responsive Design + +🌐 Client-Side Routing with react-router-dom + +πŸ’¨ Utility-First Styling with Tailwind CSS + +πŸ“¦ Uses pnpm for fast and efficient package management + + +πŸ“ Scripts + +pnpm install # Install dependencies +pnpm dev # Start development server +pnpm build # Build production-ready app +pnpm preview # Preview the built app + + +🧾 License +This project is more than educational and collaborative purposes and is part of the AltSchool Africa project work and beyond + + + +πŸ“¬ Contact +πŸ“§ Email: graphgeo02@gmail.com +🌍 GitHub: https://github.com/abdullahi-abdulkadir + + +🟒 Notes +Before you start make sure: + +Checkout the development branch: +git checkout dev +git pull origin dev + +Create a feature branch always +git checkout -b feature/ your-feature-name, example: feature/footer if you are working on footer + + +Make Change and commit: +git add . +git commit -m " feat: added footer section" ie if working on footer + +push your feature to github: +git push origin feature/footer if are working on footer for example + +Open a pull request PR: +Go to repository open pull request from your feature/footer to the dev +Request a review if need + +Important Notes: + +Do not commit directly to the main branch +Always pull from the dev before starting new work or opening a PR +Use clear and consist branch names (feature/, fix/, style) +keep your code clearn and follow project naming convention \ No newline at end of file diff --git a/faq.md b/faq.md new file mode 100644 index 0000000..398b894 --- /dev/null +++ b/faq.md @@ -0,0 +1,51 @@ +FAQ: Updating a Previously Merged Feature + +Q: I already created a feature branch (e.g., feature/footer) and it was merged into dev. and may be full requested is merge Now, after some time, I want to make additional changes to that feature. What should I do? + +A: You should create a new branch instead of reusing the old one. Here's how: + +πŸ”Ή Step-by-Step Guide + +1. Pull the Latest Changes from dev + +Make sure your local dev branch is up to date: + +git checkout dev +git pull origin dev + +2. Create a New Feature Branch + +Use a descriptive name for the new update: + +git checkout -b feature/footer-update // for example you make update on footer after 3 week + +3. Make Your Changes + +Update the component or logic as required. + +4. Commit and Push Your Changes + +git add . +git commit -m "feat: improved footer design" +git push origin feature/footer-update + +5. Create a Pull Request + +Open a new pull request from feature/footer-update into dev. The team +will review and merge it again. + +🌟 Why Not Reuse the Old Branch? + +The old branch is already merged and likely deleted from remote. + +Creating a new branch keeps Git history clean. + +It avoids confusion and potential merge conflicts. + + + + + +This approach ensures a clean, organized workflow and smooth collaboration within the team. + +You can always repeat this process for any feature you wish to improve or update later. \ No newline at end of file diff --git a/strent-app b/strent-app new file mode 160000 index 0000000..7030d7a --- /dev/null +++ b/strent-app @@ -0,0 +1 @@ +Subproject commit 7030d7acd8a7d147babc20fb3241d73ba52a3443 From d5abfec57d2943f10ed733644671b2083cdb772e Mon Sep 17 00:00:00 2001 From: Abdullahi Abdulkadir Date: Sun, 7 Sep 2025 10:27:49 +0100 Subject: [PATCH 02/11] Update contacts with api, state management, and function --- src/pages/ContactUs.jsx | 84 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/src/pages/ContactUs.jsx b/src/pages/ContactUs.jsx index cc449f8..b9f8545 100644 --- a/src/pages/ContactUs.jsx +++ b/src/pages/ContactUs.jsx @@ -7,8 +7,57 @@ import facebook from "../assets/icons/facebook.svg"; import x from "../assets/icons/x.svg"; import instagram from "../assets/icons/instagram.svg"; import tiktok from "../assets/icons/tiktok.svg"; +import { useState } from "react"; +import axios from "axios"; const Contact = () => { +const [formData, setFormData] = useState({ + fullName: '', + email: '', + subject: '', + message: '' + }); + + const [submissionStatus, setSubmissionStatus] = useState({ + loading: false, + success: false, + error: '' + }); + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); // Prevents the default browser form submission + + setSubmissionStatus({ loading: true, success: false, error: '' }); + + try { + // The local JSON server URL to post the data. + // We are posting to a new endpoint named 'messages' which is appropriate for a contact form. + const response = await axios.post('http://localhost:8080/messages', { + fullName: formData.fullName, + email: formData.email, + subject: formData.subject, + message: formData.message, + timestamp: new Date().toISOString() // Optional: add a timestamp + }); + + console.log('Form submitted successfully:', response.data); + setSubmissionStatus({ loading: false, success: true, error: '' }); + setFormData({ fullName: '', email: '', subject: '', message: '' }); // Clear form + + } catch (error) { + console.error('Error submitting form:', error); + setSubmissionStatus({ + loading: false, + success: false, + error: 'Failed to submit the form. Please try again.' + }); + } + }; + return (
@@ -73,18 +122,26 @@ const Contact = () => {

We want to hear from you!

-
+ {/* Name + Email side by side on sm+, stacked on mobile */}
@@ -94,22 +151,45 @@ const Contact = () => { type="text" placeholder="Subject" className="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-[#4B3DFE]" + name="subject" + value={formData.subject} + onChange={handleChange} + required />
+ {/* Submission status messages */} + {submissionStatus.success && ( +

+ Message sent successfully! +

+ )} + + {submissionStatus.error && ( +

+ {submissionStatus.error} +

+ )} + From fb4aae70d07339966b51052d7c28b974778bbf67 Mon Sep 17 00:00:00 2001 From: Abdullahi Abdulkadir Date: Sun, 7 Sep 2025 22:29:33 +0100 Subject: [PATCH 03/11] update footer, state, api, funtions --- data/db.json | 35 +++++++++++ src/components/Footer.jsx | 73 +++++++++++++++++++++-- src/pages/PostProperties.jsx | 0 src/pages/ResetPassword.jsx | 112 +++++++++++++++++++++++++++++++++++ 4 files changed, 216 insertions(+), 4 deletions(-) create mode 100644 src/pages/PostProperties.jsx create mode 100644 src/pages/ResetPassword.jsx diff --git a/data/db.json b/data/db.json index 0f19918..434fdc2 100644 --- a/data/db.json +++ b/data/db.json @@ -31,6 +31,41 @@ "password": "00000000Hh1&", "phoneNumber": "1234567000", "agreeToTerms": true + }, + { + "id": "oluchi@gmail.com", + "accountType": "Agent", + "fullName": "oluchi something", + "password": "00000000Hh1&", + "phoneNumber": "0918888811", + "agreeToTerms": true + } + ], + "messages": [ + { + "id": "edf7", + "fullName": "Abdullahi Abdulkadir", + "email": "graphgeo02@gmail.com", + "subject": "Scheduling a call", + "message": "Hi,\nI would like to book a meeting with you to know more about your selling properties.\nThank you.", + "timestamp": "2025-09-07T09:11:50.559Z" + } + ], + "newsletter-subscribers": [ + { + "id": "aaf9", + "email": "abdullahi@gmail.com", + "subscribedAt": "2025-09-07T21:21:58.674Z" + }, + { + "id": "bdb7", + "email": "abdullahiabdulkadir621@gmail.com", + "subscribedAt": "2025-09-07T21:22:25.210Z" + }, + { + "id": "232e", + "email": "123@gmail.com", + "subscribedAt": "2025-09-07T21:22:53.772Z" } ] } \ No newline at end of file diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx index 8f1aefb..83dfd96 100644 --- a/src/components/Footer.jsx +++ b/src/components/Footer.jsx @@ -1,4 +1,44 @@ +import React, { useState } from 'react'; +import axios from 'axios'; + + + + + const Footer = () => { + const [email, setEmail] = useState(''); + const [status, setStatus] = useState('idle'); // 'idle', 'submitting', 'success', 'error' + const handleSubmit = async (e) => { + e.preventDefault(); + setStatus('submitting'); + try { + // First, check if the email already exists in the database + const checkResponse = await axios.get(`http://localhost:8080/newsletter-subscribers?email=${email}`); + + if (checkResponse.data.length > 0) { + // If the email exists, set the status to 'exists' and stop + setStatus('exists'); + return; + } + + // If the email does not exist, proceed with the new subscription + const postResponse = await axios.post('http://localhost:8080/newsletter-subscribers', { + email: email, + subscribedAt: new Date().toISOString() + }); + + console.log('Successfully subscribed:', postResponse.data); + setStatus('success'); + setEmail(''); // Clear the input field + + } catch (error) { + console.error('Subscription error:', error); + setStatus('error'); + } + }; + + + const year = new Date().getFullYear(); return (