From 3f507e1bee7af6f9ff97c00f6b8d5a7b5f229b43 Mon Sep 17 00:00:00 2001 From: yusuf0279 Date: Wed, 8 Jul 2026 09:05:15 +0000 Subject: [PATCH] final --- package-lock.json | 179 ++++ package.json | 1 + src/components/Layout.jsx | 9 +- src/components/PageShell.jsx | 8 - src/components/SafeHtml.jsx | 9 + src/components/sections/Breadcrumb.jsx | 22 + src/components/sections/Button.jsx | 9 + src/components/sections/ContactForm.jsx | 48 + src/components/sections/ContactInfo.jsx | 21 + src/components/sections/Divider.jsx | 11 + src/components/sections/FeatureCards.jsx | 41 + src/components/sections/Footer.jsx | 188 ++++ src/components/sections/GoogleMap.jsx | 11 + src/components/sections/Header.jsx | 131 +++ src/components/sections/PhoneWidget.jsx | 11 + src/components/sections/ProjectFilterGrid.jsx | 51 ++ src/components/sections/SectionTitle.jsx | 14 + src/components/sections/ServiceBody.jsx | 18 + src/components/sections/ServiceBreadcrumb.jsx | 17 + .../sections/ServiceContentBlocks.jsx | 34 + .../sections/ServiceGridSection.jsx | 37 + src/components/sections/ServiceImage.jsx | 19 + src/components/sections/ServiceSidebar.jsx | 31 + src/config.js | 24 + src/data/contact-content.html | 95 -- src/data/layout-footer.html | 60 -- src/data/layout-header.html | 26 - src/data/project-content.html | 15 - src/data/servicePages.js | 373 -------- src/data/services.json | 848 ++++++++++++++++++ src/pages/About.jsx | 4 +- src/pages/Contact.jsx | 74 +- src/pages/Home.jsx | 4 +- src/pages/Project.jsx | 20 +- src/pages/ServiceDetail.jsx | 46 +- src/pages/Services.jsx | 4 +- 36 files changed, 1910 insertions(+), 603 deletions(-) delete mode 100644 src/components/PageShell.jsx create mode 100644 src/components/SafeHtml.jsx create mode 100644 src/components/sections/Breadcrumb.jsx create mode 100644 src/components/sections/Button.jsx create mode 100644 src/components/sections/ContactForm.jsx create mode 100644 src/components/sections/ContactInfo.jsx create mode 100644 src/components/sections/Divider.jsx create mode 100644 src/components/sections/FeatureCards.jsx create mode 100644 src/components/sections/Footer.jsx create mode 100644 src/components/sections/GoogleMap.jsx create mode 100644 src/components/sections/Header.jsx create mode 100644 src/components/sections/PhoneWidget.jsx create mode 100644 src/components/sections/ProjectFilterGrid.jsx create mode 100644 src/components/sections/SectionTitle.jsx create mode 100644 src/components/sections/ServiceBody.jsx create mode 100644 src/components/sections/ServiceBreadcrumb.jsx create mode 100644 src/components/sections/ServiceContentBlocks.jsx create mode 100644 src/components/sections/ServiceGridSection.jsx create mode 100644 src/components/sections/ServiceImage.jsx create mode 100644 src/components/sections/ServiceSidebar.jsx delete mode 100644 src/data/contact-content.html delete mode 100644 src/data/layout-footer.html delete mode 100644 src/data/layout-header.html delete mode 100644 src/data/project-content.html delete mode 100644 src/data/servicePages.js create mode 100644 src/data/services.json diff --git a/package-lock.json b/package-lock.json index c0d64d2..b1bcf64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@fortawesome/fontawesome-free": "^7.3.0", + "html-react-parser": "^6.1.4", "react": "^19.2.6", "react-dom": "^19.2.6", "react-router-dom": "^7.17.0" @@ -1120,6 +1121,73 @@ "node": ">=8" } }, + "node_modules/dom-serializer": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-3.1.1.tgz", + "integrity": "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw==", + "license": "MIT", + "dependencies": { + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "entities": "^8.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-3.0.0.tgz", + "integrity": "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/domhandler": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-6.0.1.tgz", + "integrity": "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^3.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-4.0.2.tgz", + "integrity": "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^3.0.0", + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.371", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.371.tgz", @@ -1127,6 +1195,18 @@ "dev": true, "license": "ISC" }, + "node_modules/entities": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz", + "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -1490,6 +1570,75 @@ "hermes-estree": "0.25.1" } }, + "node_modules/html-dom-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-8.0.0.tgz", + "integrity": "sha512-cWLJ8mt930VceOzVfY/J+T1ou9v3ENT0BgWqy5aEZjdFp37TYLXULjX8u0vD2rBpFAkK5IofOPl0y4Gq0QLIyA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/remarkablemark" + } + ], + "license": "MIT", + "dependencies": { + "domhandler": "6.0.1", + "htmlparser2": "12.0.0" + } + }, + "node_modules/html-react-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-6.1.4.tgz", + "integrity": "sha512-oNZVIuYir7XOFuQZ7mtvcIC5cTYBVqCDOhJ1rSH4V1nVDs71bHZXFlKdpSuOm5TZT7V2uxCxA7HqTkCNHW32KQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/remarkablemark" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/html-react-parser" + } + ], + "license": "MIT", + "dependencies": { + "domhandler": "6.0.1", + "html-dom-parser": "8.0.0", + "react-property": "2.0.2", + "style-to-js": "2.0.1" + }, + "peerDependencies": { + "@types/react": "0.14 || 15 || 16 || 17 || 18 || 19", + "react": "0.14 || 15 || 16 || 17 || 18 || 19" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-12.0.0.tgz", + "integrity": "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^3.0.0", + "domhandler": "^6.0.0", + "domutils": "^4.0.2", + "entities": "^8.0.0" + }, + "engines": { + "node": ">=20.19.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -1510,6 +1659,12 @@ "node": ">=0.8.19" } }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "license": "MIT" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2136,6 +2291,12 @@ "react": "^19.2.7" } }, + "node_modules/react-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", + "integrity": "sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==", + "license": "MIT" + }, "node_modules/react-router": { "version": "7.17.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.17.0.tgz", @@ -2263,6 +2424,24 @@ "node": ">=0.10.0" } }, + "node_modules/style-to-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-2.0.1.tgz", + "integrity": "sha512-j5whjFV29FyWf+/gWc/Fax7DQqojc5CzZ2kxOCuSMoZDGdciF+Ki1HyZ/GPOxdbfIw0suKUBmG1I3qa7JZKRTA==", + "license": "MIT", + "dependencies": { + "style-to-object": "2.0.0" + } + }, + "node_modules/style-to-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-2.0.0.tgz", + "integrity": "sha512-3zaRtBpwCy9AnYQYfgZ8tIMPn/PlQpW3wtRMB+w0xVtBzo8/m7KKGi7cR56yQ6udLz5MPzwRqfKOZ3O+Oc6VpA==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/tinyglobby": { "version": "0.2.17", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", diff --git a/package.json b/package.json index c2d01d1..7fee3a6 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@fortawesome/fontawesome-free": "^7.3.0", + "html-react-parser": "^6.1.4", "react": "^19.2.6", "react-dom": "^19.2.6", "react-router-dom": "^7.17.0" diff --git a/src/components/Layout.jsx b/src/components/Layout.jsx index b8fbd83..774d7bc 100644 --- a/src/components/Layout.jsx +++ b/src/components/Layout.jsx @@ -1,8 +1,7 @@ import { useEffect } from 'react' import { Outlet, useLocation } from 'react-router-dom' -import PageShell from './PageShell' -import headerHtml from '../data/layout-header.html?raw' -import footerHtml from '../data/layout-footer.html?raw' +import Header from './sections/Header' +import Footer from './sections/Footer' import WhatsAppButton from './WhatsAppButton' import useThemeAssets from '../hooks/useThemeAssets' import useLayoutInit from '../hooks/useLayoutInit' @@ -68,9 +67,9 @@ export default function Layout() { return ( <> - +
- +