diff --git a/package.json b/package.json index d6e273d..c5dba84 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@payloadcms/plugin-form-builder": "^3.35.1", "@payloadcms/richtext-lexical": "^3.35.1", "@payloadcms/storage-s3": "^3.35.1", + "clsx": "^2.1.1", "country-state-city": "^3.2.1", "dayjs": "^1.11.13", "graphql": "^16.8.1", @@ -29,7 +30,8 @@ "react-hook-form": "^7.56.1", "react-select": "^5.10.1", "react-toastify": "^11.0.5", - "swiper": "^11.2.6" + "swiper": "^11.2.6", + "tailwind-merge": "^3.2.0" }, "devDependencies": { "@eslint/eslintrc": "^3", diff --git a/public/css/style.css b/public/css/style.css index b223537..021cd23 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -3744,13 +3744,13 @@ html .page .divider-secondary::after { } .button-primary, .button-primary:focus { - color: #ffffff; - background-color: #bc986b; - border-color: #bc986b; + color: var(--color-colorBtnPrimaryText); + background-color: var(--color-colorBtnPrimary); + border-color: var(--color-colorBtnPrimary); } .button-primary:hover, .button-primary:active { - color: #151515; + color: var(--color-colorBtnPrimaryText); opacity: 0.8; } @@ -3759,15 +3759,14 @@ html .page .divider-secondary::after { } .button-secondary, .button-secondary:focus { - color: #151515; - background-color: #fdde52; - border-color: #fdde52; + color: var(--color-colorBtnSecondaryText); + background-color: var(--color-colorBtnSecondary); + border-color: var(--color-colorBtnSecondary); } .button-secondary:hover, .button-secondary:active { - color: #ffffff; - background-color: #bc986b; - border-color: #bc986b; + color: var(--color-colorBtnSecondaryText); + opacity: 0.8; } .button-secondary.button-ujarak::before { @@ -11354,7 +11353,7 @@ html:not(.lt-ie10) .not-animated { .ui-to-top:hover { color: #151515; - background: #fdde52; + opacity: 0.8; text-decoration: none; } @@ -11699,7 +11698,7 @@ html.tablet .ui-to-top { } .rd-navbar-static .rd-menu { - z-index: 15; + z-index: 30; position: absolute; display: block; visibility: hidden; diff --git a/public/images/bg-header4.jpg b/public/images/bg-header4.jpg new file mode 100644 index 0000000..dd25fe9 Binary files /dev/null and b/public/images/bg-header4.jpg differ diff --git a/public/images/bg-header5.jpg b/public/images/bg-header5.jpg new file mode 100644 index 0000000..66f9540 Binary files /dev/null and b/public/images/bg-header5.jpg differ diff --git a/public/images/home1.jpg b/public/images/home1.jpg new file mode 100644 index 0000000..57da5df Binary files /dev/null and b/public/images/home1.jpg differ diff --git a/public/images/home2.jpg b/public/images/home2.jpg new file mode 100644 index 0000000..cff44c5 Binary files /dev/null and b/public/images/home2.jpg differ diff --git a/public/images/home3.jpg b/public/images/home3.jpg new file mode 100644 index 0000000..1708490 Binary files /dev/null and b/public/images/home3.jpg differ diff --git a/public/images/home4.jpg b/public/images/home4.jpg new file mode 100644 index 0000000..568ca7d Binary files /dev/null and b/public/images/home4.jpg differ diff --git a/public/images/home5.jpg b/public/images/home5.jpg new file mode 100644 index 0000000..e8d6ad3 Binary files /dev/null and b/public/images/home5.jpg differ diff --git a/public/images/home6.jpg b/public/images/home6.jpg new file mode 100644 index 0000000..064ec5f Binary files /dev/null and b/public/images/home6.jpg differ diff --git a/public/images/home7.jpg b/public/images/home7.jpg new file mode 100644 index 0000000..7f8dc5b Binary files /dev/null and b/public/images/home7.jpg differ diff --git a/public/images/logo1.png b/public/images/logo1.png new file mode 100644 index 0000000..db2b929 Binary files /dev/null and b/public/images/logo1.png differ diff --git a/src/app/(main)/[slug]/loading.tsx b/src/app/(main)/[slug]/loading.tsx new file mode 100644 index 0000000..779bae8 --- /dev/null +++ b/src/app/(main)/[slug]/loading.tsx @@ -0,0 +1,5 @@ +import LoaderFixed from "@/components/loaders/LoaderFixed"; + +export default function Loading() { + return ; +} diff --git a/src/app/(main)/[slug]/page.tsx b/src/app/(main)/[slug]/page.tsx new file mode 100644 index 0000000..7a098b9 --- /dev/null +++ b/src/app/(main)/[slug]/page.tsx @@ -0,0 +1,111 @@ +import DetailPageBlog from "@/components/blogs/DetailPageBlog"; +import DetailPage from "@/components/pages/DetailPage"; +import { fetchBlogDetail } from "@/services/payload/blog"; +import { fetchPageBySlug } from "@/services/payload/page"; +import { getDefaultMetadata } from "@/utils/metadata"; +import { Metadata } from "next"; +import { headers } from "next/headers"; +import { notFound } from "next/navigation"; + +export async function generateMetadata(props: { params: Promise<{ slug: string }> }): Promise { + const metadata = await getDefaultMetadata(); + const params = await props.params; + + let title = `Page Not Found - ${metadata.openGraph?.siteName}`; + let description = title; + let publishedAt = ""; + let updatedAt = ""; + let imgUrl = ""; + let createdByName = ""; + let canonicalUrl = ""; + + const blog = await fetchBlogDetail(params.slug); + if (!!blog) { + // check for blog data + title = `${!!blog.data?.meta?.title ? blog.data?.meta?.title : blog.data.title} - ${metadata.openGraph?.siteName}`; + description = `${!!blog.data?.meta?.description ? blog.data?.meta?.description : blog.data.title}`; + imgUrl = blog.img.url; + publishedAt = blog.data.createdAt; + updatedAt = blog.data.updatedAt; + if (!!blog.data?.meta?.canonical_url) { + canonicalUrl = blog.data.meta.canonical_url; + } + if (!!blog?.data?.createdBy && typeof blog.data.createdBy !== "number") { + createdByName = blog.data.createdBy?.name ?? ""; + } + } else { + // check for page data when blog is not found + const page = await fetchPageBySlug({ slug: params.slug }); + if (!!page) { + title = `${!!page?.data?.meta?.title ? page?.data?.meta?.title : page.data.title} - ${metadata.openGraph?.siteName}`; + description = `${!!page?.data?.meta?.description ? page?.data?.meta?.description : page.data.title}`; + imgUrl = page.heroImg?.url; + publishedAt = page.createdAt; + updatedAt = page.updatedAt; + if (!!page.data?.meta?.canonical_url) { + canonicalUrl = page.data.meta.canonical_url; + } + if (!!page?.data?.createdBy && typeof page?.data?.createdBy !== "number") { + createdByName = page?.data?.createdBy?.name ?? ""; + } + } + } + + metadata.title = title; + metadata.description = description; + if (!!metadata.openGraph) { + // @ts-ignore + metadata.openGraph.type = "article"; + metadata.openGraph.title = title; + metadata.openGraph.description = description; + metadata.openGraph.images = !!imgUrl ? [imgUrl] : undefined; + } + if (!!metadata.alternates && !!canonicalUrl) { + metadata.alternates.canonical = canonicalUrl; + } + metadata.twitter = { + card: "summary_large_image", + title: title, + description: description, + images: !!imgUrl ? [imgUrl] : undefined, + }; + metadata.other = { + "article:published_time": publishedAt, + "article:modified_time": updatedAt, + "twitter:label1": "Written by", + "twitter:data1": !!createdByName ? createdByName : "Admin", + "twitter:label2": "Est. reading time", + "twitter:data2": "3 minutes", + }; + + return metadata; +} + +export default async function SinglePage(props: { params: Promise<{ slug: string }> }) { + const params = await props.params; + const headersList = await headers(); + const fullUrl = headersList.get("x-full-url"); + const shareUrl = { + facebook: `https://www.facebook.com/sharer/sharer.php?u=${fullUrl}`, + linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${fullUrl}`, + twitter: `https://twitter.com/intent/tweet?url=${fullUrl}`, + }; + + const blog = await fetchBlogDetail(params.slug); + if (!!blog) { + return ( + <> + + + ); + } + + const page = await fetchPageBySlug({ slug: params.slug }); + if (!page) return notFound(); + + return ( + <> + + + ); +} diff --git a/src/app/(main)/blog/[slug]/page.tsx b/src/app/(main)/blog/[slug]/page.tsx index 8287882..9837964 100644 --- a/src/app/(main)/blog/[slug]/page.tsx +++ b/src/app/(main)/blog/[slug]/page.tsx @@ -1,19 +1,16 @@ -import ListOfRecentBlog from "@/components/blogs/ListOfRecentBlog"; -import HeroImage from "@/components/HeroImage"; +import DetailPageBlog from "@/components/blogs/DetailPageBlog"; import { fetchBlogDetail } from "@/services/payload/blog"; import { getDefaultMetadata } from "@/utils/metadata"; -import { RichText } from "@payloadcms/richtext-lexical/react"; import { Metadata } from "next"; import { headers } from "next/headers"; -import Image from "next/image"; import { notFound } from "next/navigation"; export async function generateMetadata(props: { params: Promise<{ slug: string }> }): Promise { const metadata = await getDefaultMetadata(); const params = await props.params; - let title = "Page"; - let description = "Page"; + let title = `Page Not Found - ${metadata.openGraph?.siteName}`; + let description = title; let publishedAt = ""; let updatedAt = ""; let imgUrl = ""; @@ -81,135 +78,7 @@ export default async function BlogDetail(props: { params: Promise<{ slug: string return ( <> - - -
-
-
-
-
-
-
- {blog.img.alt} -
- - -
- -
-
- -
-
-
    -
  • - Share this post -
  • -
  • - -
  • -
  • - -
  • -
  • - -
  • -
-
-
- - -
-
- - {/* Sidebar */} - -
-
-
+ ); } diff --git a/src/app/(main)/globals.css b/src/app/(main)/globals.css index f7699f9..bd23a93 100644 --- a/src/app/(main)/globals.css +++ b/src/app/(main)/globals.css @@ -33,8 +33,15 @@ --color-colorContactForm: var(--color-colorExt50); --color-colorText1: var(--color-colorExt10); --color-colorText2: var(--color-colorExt20); + --color-colorText3: var(--color-colorExt30); --color-colorLoaderBackground: var(--color-colorExt20); --color-colorPriceTag: var(--color-colorExt30); + --color-colorBtnPrimary: var(--color-colorext40); + --color-colorBtnPrimaryText: var(--color-colorExt20); + --color-colorBtnSecondary: var(--color-colorExt50); + --color-colorBtnSecondaryText: var(--color-colorExt20); + --color-colorLinkText1: var(--color-colorExt30); + --color-colorLinkText2: var(--color-colorext40); } @layer components { diff --git a/src/app/(main)/page.tsx b/src/app/(main)/page.tsx index a7ec3a8..330ade6 100644 --- a/src/app/(main)/page.tsx +++ b/src/app/(main)/page.tsx @@ -1,10 +1,5 @@ import GoogleReviewBox from "@/components/GoogleReviewBox"; import HomeTopSection from "@/components/homes/HomeTopSection"; -import Loader from "@/components/loaders/Loader"; -import ListOfFeaturedProperty from "@/components/properties/ListOfFeaturedProperty"; -import Image from "next/image"; -import Link from "next/link"; -import { Suspense } from "react"; export default function Home() { return ( @@ -13,95 +8,57 @@ export default function Home() {
+

+ Why Dynamic Realty? +

-
- +
+
- +
+ +
-

Buy

-

- Discover a wide selection of properties available for purchase in prime locations at competitive - prices. +

Tailored Management, Trusted Care

+

+ Committed to providing a personalized structure to each client, with on-site management & a robust + property management

- -
-
- -
- -
-

Sell

-

- List your property with ease and reach potential buyers quickly with our expert marketing support. -

-
-
- -
-
- -
- -
-

Rent

-

Find the perfect rental home or apartment with flexible lease terms and no hidden fees.

-
-
- -
-
- -
- -
-

Need Help?

-

- Have questions? Our support team is here to guide you through every step of your real estate - journey. -

-
-
- -
-
-
-
- -
- Experience the Difference in Every Key Turn -
-
-
-
-

Experience the Difference in Every Key Turn

-
-

- Dynamic Realty is a full-service veteran-owned real estate company based in Centerville, GA, - established in 2004. Our services include buying & selling, rentals, & property management. We are - committed to providing a personalized structure to each client, with on-site management & a robust - property management division. We strive to provide a service that meets the needs of all our customers - & are proud to have been helping people with their real estate needs for the past 20 years. -

-

- At Dynamic Realty, we offer a comprehensive range of realty services to meet the needs of our - customers in Central Georgia. Our services include buying & selling, renting, & property management. - We understand the real estate sector inside out & are committed to providing a professional service to - our clients. We strive to make the process of reaching your real estate goals as easy & stress-free as - possible. Get in touch with us today to find out more. -

+
+
+
+
+
+ +
+
+

20 Years of Real Estate Excellence

+

+ We strive to provide a service that meets the needs of all our customers & are proud to have been + helping people with their real estate needs for the past 20 years +

+
+
+
+
+
+
+
+
+ +
+
+

Expert Guidance, Stress-Free Journeys

+

+ We understand the real estate sector inside out & are committed to providing a professional + service to our clients. We strive to make the process of reaching your real estate goals as easy & + stress-free as possible +

+
+
@@ -109,101 +66,6 @@ export default function Home() {
- -
-
-
-

- Featured Properties -

-
- -
-
-
- -
- -
- - } - > - -
-
-
-
- -
-
-
-
-
-
-
- 860 -
-

Properties on Map

-
-
-
-
-
-
29
-
-

Professional Agents

-
-
-
-
-
-
10
- k -
-

Happy Clients

-
-
-
-
-
-
15
-
-

New Apartments Daily

-
-
-
-
-
-
- -
-
-

- Find Us -

-
-
-