Audit fixes: VIP self-grant, draft leak, onboarding flag, hero personalization, gated downloads
Deploy GitHub Pages / deploy (push) Canceled after 0s
Deploy GitHub Pages / deploy (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/* Views ping — counts one view per browser session per post (global counter
|
||||
on the backend). */
|
||||
export function ViewPing({ slug }: { slug: string }) {
|
||||
useEffect(() => {
|
||||
const key = `anw-viewed:${slug}`
|
||||
try {
|
||||
if (sessionStorage.getItem(key)) return
|
||||
sessionStorage.setItem(key, '1')
|
||||
} catch { /* private mode — count anyway */ }
|
||||
fetch(`/api/posts/${slug}/view`, { method: 'POST', keepalive: true }).catch(() => null)
|
||||
}, [slug])
|
||||
return null
|
||||
}
|
||||
|
||||
/* Like toggle — login required; one like per user per post. */
|
||||
export function LikeButton({ slug, loggedIn, initialLiked, initialCount }: { slug: string; loggedIn: boolean; initialLiked: boolean; initialCount: number }) {
|
||||
const [liked, setLiked] = useState(initialLiked)
|
||||
const [count, setCount] = useState(initialCount)
|
||||
const [busy, setBusy] = useState(false)
|
||||
|
||||
async function toggle() {
|
||||
if (!loggedIn) {
|
||||
location.href = `/login?next=/posts/${slug}`
|
||||
return
|
||||
}
|
||||
setBusy(true)
|
||||
const res = await fetch(`/api/posts/${slug}/like`, { method: 'POST' })
|
||||
if (res.ok) {
|
||||
const data = await res.json()
|
||||
setLiked(data.liked)
|
||||
setCount(data.likes)
|
||||
}
|
||||
setBusy(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className="like"
|
||||
type="button"
|
||||
onClick={toggle}
|
||||
disabled={busy}
|
||||
aria-pressed={liked}
|
||||
aria-label={liked ? 'ألغِ الإعجاب' : 'أعجبني'}
|
||||
>
|
||||
<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 13.5 2.6 8.3a3.2 3.2 0 0 1 4.5-4.6L8 4.6l.9-.9a3.2 3.2 0 0 1 4.5 4.6Z" fill="none" stroke="currentColor" strokeWidth="1.4" /></svg>
|
||||
<span>{count}</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user