97 lines
3.4 KiB
TypeScript
97 lines
3.4 KiB
TypeScript
import { useEffect, useMemo, useState } from "react";
|
||
import type { Dictionary } from "@/lib/i18n";
|
||
import type { Locale } from "@/lib/i18n";
|
||
import { buildShareText, buildShareUrl } from "@/lib/share";
|
||
import type { DailyProgress, GlobalStats } from "@/lib/types";
|
||
import StatsPanel from "./StatsPanel";
|
||
|
||
type ShareResultProps = {
|
||
dateKey: string;
|
||
onClose: () => void;
|
||
progress: DailyProgress;
|
||
locale: Locale;
|
||
quote: { author: string; text: Record<Locale, string> };
|
||
stats: GlobalStats;
|
||
t: Dictionary;
|
||
};
|
||
|
||
export default function ShareResult({ dateKey, locale, onClose, progress, quote, stats, t }: ShareResultProps) {
|
||
const [shared, setShared] = useState(false);
|
||
const [origin, setOrigin] = useState("https://hidden11.app");
|
||
const shareUrl = useMemo(() => buildShareUrl(dateKey, progress, origin), [dateKey, origin, progress]);
|
||
const shareText = useMemo(() => buildShareText(dateKey, progress, t, shareUrl), [dateKey, progress, shareUrl, t]);
|
||
|
||
useEffect(() => {
|
||
setOrigin(window.location.origin);
|
||
}, []);
|
||
|
||
async function share() {
|
||
if (navigator.share) {
|
||
await navigator.share({
|
||
title: "hidden11",
|
||
text: shareText,
|
||
});
|
||
setShared(true);
|
||
window.setTimeout(() => setShared(false), 1600);
|
||
return;
|
||
}
|
||
|
||
window.open(
|
||
`https://twitter.com/intent/tweet?text=${encodeURIComponent(shareText)}`,
|
||
"_blank",
|
||
"noopener,noreferrer",
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="fixed inset-0 z-50 flex items-end bg-black/70 p-3 backdrop-blur-sm sm:items-center sm:justify-center">
|
||
<div
|
||
className="flex max-h-[92dvh] w-full flex-col overflow-hidden rounded-lg border border-white/10 bg-pitch-950 shadow-2xl sm:max-w-lg"
|
||
role="dialog"
|
||
aria-modal="true"
|
||
aria-labelledby="share-title"
|
||
>
|
||
<div className="flex items-center justify-between gap-3 border-b border-white/10 p-4">
|
||
<div>
|
||
<h2 id="share-title" className="text-lg font-black text-white">
|
||
{t.share}
|
||
</h2>
|
||
<p className="mt-0.5 text-sm text-white/55">{t.shareLead}</p>
|
||
</div>
|
||
<div className="flex items-center gap-2">
|
||
<button
|
||
type="button"
|
||
onClick={share}
|
||
className="h-9 rounded-full bg-emerald-400 px-4 text-xs font-black uppercase tracking-wide text-pitch-950 transition hover:bg-emerald-300"
|
||
>
|
||
{shared ? t.copied : t.shareNow}
|
||
</button>
|
||
<button
|
||
type="button"
|
||
onClick={onClose}
|
||
className="h-9 w-9 rounded-full border border-white/15 text-lg font-black text-white transition hover:bg-white/10"
|
||
aria-label={t.closeModal}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="min-h-0 flex-1 overflow-y-auto p-4">
|
||
<StatsPanel stats={stats} t={t} />
|
||
<div className="mt-4 rounded-md border border-emerald-300/20 bg-emerald-300/10 p-3">
|
||
<p className="text-sm font-semibold leading-6 text-emerald-50">
|
||
“{quote.text[locale]}”
|
||
</p>
|
||
<p className="mt-1 text-xs font-bold uppercase text-emerald-100/55">{quote.author}</p>
|
||
</div>
|
||
<pre className="mt-4 max-h-[38vh] overflow-auto whitespace-pre-wrap rounded-md bg-black/30 p-3 text-sm leading-6 text-white/85">
|
||
{shareText}
|
||
</pre>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|