Skip to content

Commit 7a1c239

Browse files
authored
✨ feat(jobs): add social share buttons to job detail page UI (#256)
Added dedicated Facebook, Twitter/X, LinkedIn, and Telegram share buttons on job detail pages with pre-filled share links, and refactored duplicated share UI into a reusable local component(including responsive behavior).
1 parent de8e0a1 commit 7a1c239

1 file changed

Lines changed: 71 additions & 23 deletions

File tree

src/app/jobs/post/JobPostClient.tsx

Lines changed: 71 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
ArrowLeft,
1010
Tag,
1111
Briefcase,
12-
Share2,
1312
FileText,
1413
Mail,
1514
CalendarClock,
@@ -23,6 +22,58 @@ import type { JobPost } from "@/lib/firebase/types";
2322
import { useTranslations } from "next-intl";
2423
import { useLanguage } from "@/hooks/useLanguage";
2524
import { khitHaungg } from "@/fonts/fonts";
25+
import {
26+
FaFacebookF,
27+
FaXTwitter,
28+
FaLinkedinIn,
29+
FaTelegram,
30+
} from "react-icons/fa6";
31+
import type { IconType } from "react-icons";
32+
33+
type SharePlatform = "facebook" | "twitter" | "linkedin" | "telegram";
34+
35+
function ShareActions({
36+
shareLabel,
37+
onShare,
38+
}: {
39+
shareLabel: string;
40+
onShare: (platform: SharePlatform) => void;
41+
}) {
42+
const platforms: Array<{
43+
platform: SharePlatform;
44+
label: string;
45+
icon: IconType;
46+
}> = [
47+
{ platform: "facebook", label: "Facebook", icon: FaFacebookF },
48+
{ platform: "twitter", label: "Twitter/X", icon: FaXTwitter },
49+
{ platform: "linkedin", label: "LinkedIn", icon: FaLinkedinIn },
50+
{ platform: "telegram", label: "Telegram", icon: FaTelegram },
51+
];
52+
53+
const buttonClassName =
54+
"w-8 h-8 sm:w-auto sm:h-auto sm:px-2.5 sm:py-1.5 rounded-lg text-[10px] font-mono uppercase tracking-wider text-zinc-500 hover:text-zinc-200 bg-white/[0.03] border border-white/[0.06] hover:border-white/[0.1] transition-all duration-200 flex items-center justify-center";
55+
56+
return (
57+
<div className="flex items-center gap-2 sm:gap-2.5">
58+
<span className="hidden sm:inline text-[10px] font-mono uppercase tracking-wider text-zinc-600 mr-1.5">{shareLabel}</span>
59+
{platforms.map(({ platform, label, icon: Icon }) => (
60+
<button
61+
key={platform}
62+
type="button"
63+
onClick={() => onShare(platform)}
64+
className={buttonClassName}
65+
aria-label={`Share this job on ${label}`}
66+
title={`Share this job on ${label}`}
67+
>
68+
<span aria-hidden="true" className="sm:hidden text-[12px]">
69+
<Icon />
70+
</span>
71+
<span className="hidden sm:inline">{label}</span>
72+
</button>
73+
))}
74+
</div>
75+
);
76+
}
2677

2778
function JobPostInner() {
2879
const searchParams = useSearchParams();
@@ -136,12 +187,23 @@ function JobPostInner() {
136187
year: "numeric",
137188
});
138189

139-
const handleShare = async () => {
140-
if (navigator.share) {
141-
await navigator.share({ title: post.position, url: window.location.href });
142-
} else {
143-
await navigator.clipboard.writeText(window.location.href);
144-
}
190+
const getShareLinks = () => {
191+
const url = window.location.href;
192+
const text = `Check out this job: ${post.position}`;
193+
const encodedUrl = encodeURIComponent(url);
194+
const encodedText = encodeURIComponent(text);
195+
196+
return {
197+
facebook: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`,
198+
twitter: `https://twitter.com/intent/tweet?text=${encodedText}&url=${encodedUrl}`,
199+
linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${encodedUrl}`,
200+
telegram: `https://t.me/share/url?url=${encodedUrl}&text=${encodedText}`,
201+
};
202+
};
203+
204+
const openShare = (platform: SharePlatform) => {
205+
const links = getShareLinks();
206+
window.open(links[platform], "_blank", "noopener,noreferrer");
145207
};
146208

147209
return (
@@ -172,14 +234,7 @@ function JobPostInner() {
172234
<span className="font-mono text-xs uppercase tracking-wider">{t("allJobs")}</span>
173235
</MseLink>
174236

175-
<button
176-
type="button"
177-
onClick={handleShare}
178-
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[11px] font-mono uppercase tracking-wider text-zinc-500 hover:text-zinc-200 bg-white/[0.03] border border-white/[0.06] hover:border-white/[0.1] transition-all duration-200"
179-
>
180-
<Share2 className="w-3 h-3" />
181-
{t("share")}
182-
</button>
237+
<ShareActions shareLabel={t("share")} onShare={openShare} />
183238
</motion.div>
184239

185240
{/* Header card */}
@@ -424,14 +479,7 @@ function JobPostInner() {
424479
<span className="font-mono text-xs uppercase tracking-wider">{t("allJobs")}</span>
425480
</MseLink>
426481

427-
<button
428-
type="button"
429-
onClick={handleShare}
430-
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[11px] font-mono uppercase tracking-wider text-zinc-500 hover:text-zinc-200 bg-white/[0.03] border border-white/[0.06] hover:border-white/[0.1] transition-all duration-200"
431-
>
432-
<Share2 className="w-3 h-3" />
433-
{t("share")}
434-
</button>
482+
<ShareActions shareLabel={t("share")} onShare={openShare} />
435483
</div>
436484
</motion.div>
437485
</article>

0 commit comments

Comments
 (0)