Merge branch 'main' into rte-posts-upgrade
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import PublicLayout from '../../components/PublicLayout.jsx'
|
||||
import HeroElement from '../../components/HeroElement.jsx'
|
||||
import { useSite } from '../../contexts/SiteContext.jsx'
|
||||
|
||||
const HERO_BG =
|
||||
"linear-gradient(90deg,rgba(11,15,20,0.34) 0%,rgba(11,15,20,0.5) 36%,rgba(11,15,20,0.78) 62%,rgba(11,15,20,0.66) 100%),linear-gradient(180deg,rgba(11,15,20,0.08) 0%,rgba(11,15,20,0.72) 100%),url('/assets/img/uomysticmoon-main-hero.png')"
|
||||
import { api } from '../../api/client.js'
|
||||
import { defaultLayout, parseLayout, heroBackground } from '../../lib/heroLayout.js'
|
||||
|
||||
const QUICK = [
|
||||
{ label: 'News', to: '/site/news' },
|
||||
@@ -28,53 +29,63 @@ const DESTINATIONS = [
|
||||
},
|
||||
]
|
||||
|
||||
// Admin "Preview" opens the portal with ?preview=1 to render the unpublished draft.
|
||||
const PREVIEW = typeof window !== 'undefined' && new URLSearchParams(window.location.search).get('preview') === '1'
|
||||
|
||||
export default function Portal() {
|
||||
const { settings } = useSite()
|
||||
const teaser =
|
||||
settings.homepage_teaser ||
|
||||
'Mysticmoon is still being shaped beneath a midnight sky — a quiet preview for the news, screenshots, guides, and community notes to come as the world wakes.'
|
||||
|
||||
// Published layout (public). Falls back to the pre-populated default if missing,
|
||||
// malformed, the wrong version, or empty — so the hero is never blank.
|
||||
const published = useMemo(() => parseLayout(settings.hero_layout), [settings.hero_layout])
|
||||
|
||||
// In preview mode, pull the draft via the admin endpoint (requires a logged-in
|
||||
// admin cookie); falls back silently to the published/default layout otherwise.
|
||||
const [draft, setDraft] = useState(null)
|
||||
useEffect(() => {
|
||||
if (!PREVIEW) return
|
||||
let active = true
|
||||
api.admin
|
||||
.getSettings()
|
||||
.then((s) => active && setDraft(parseLayout(s.hero_layout_draft)))
|
||||
.catch(() => {})
|
||||
return () => {
|
||||
active = false
|
||||
}
|
||||
}, [])
|
||||
|
||||
const active = (PREVIEW && draft) || (published && published.elements.length ? published : null)
|
||||
const layout = active || defaultLayout(teaser)
|
||||
const isDefault = !active
|
||||
const bgStyle = heroBackground(layout, { isDefault })
|
||||
const elements = [...layout.elements].sort((a, b) => (a.z || 0) - (b.z || 0))
|
||||
|
||||
return (
|
||||
<PublicLayout header={false}>
|
||||
<main style={{ minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
|
||||
{PREVIEW && draft && (
|
||||
<div
|
||||
className="sans"
|
||||
style={{ background: 'var(--accent)', color: 'var(--bg-deep)', textAlign: 'center', padding: '6px 12px', fontSize: '0.8rem', fontWeight: 700, letterSpacing: '0.04em' }}
|
||||
>
|
||||
Preview — showing unpublished draft
|
||||
</div>
|
||||
)}
|
||||
<section
|
||||
style={{
|
||||
position: 'relative',
|
||||
display: 'grid',
|
||||
alignContent: 'center',
|
||||
minHeight: 'clamp(600px,72vh,860px)',
|
||||
padding: '96px max(18px,calc((100% - 1080px)/2)) 96px',
|
||||
overflow: 'hidden',
|
||||
textAlign: 'center',
|
||||
backgroundColor: 'var(--bg-deep)',
|
||||
backgroundImage: HERO_BG,
|
||||
backgroundPosition: 'left center',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
backgroundSize: 'cover',
|
||||
...bgStyle,
|
||||
}}
|
||||
>
|
||||
<div style={{ maxWidth: 760, margin: '0 auto', textShadow: '0 2px 22px rgba(0,0,0,0.82)' }}>
|
||||
<p className="eyebrow" style={{ color: '#c2d2e6', letterSpacing: '0.22em' }}>
|
||||
Private shard project
|
||||
</p>
|
||||
<h1
|
||||
className="display"
|
||||
style={{ margin: 0, fontSize: 'clamp(3rem,8.5vw,5.75rem)', lineHeight: 1, letterSpacing: '0.02em' }}
|
||||
>
|
||||
UOMysticmoon
|
||||
</h1>
|
||||
<p style={{ margin: '22px auto 0', color: '#dbe2ea', fontSize: '1.32rem', fontStyle: 'italic' }}>
|
||||
A private Ultima Online world in progress
|
||||
</p>
|
||||
<p style={{ maxWidth: 600, margin: '22px auto 0', color: '#c4cdd8', fontSize: '1.06rem' }}>{teaser}</p>
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, justifyContent: 'center', marginTop: 34 }}>
|
||||
<Link to="/site" className="btn btn-primary">
|
||||
Enter the Website
|
||||
</Link>
|
||||
<Link to="/wiki" className="btn btn-ghost">
|
||||
Open the Wiki
|
||||
</Link>
|
||||
</div>
|
||||
<div style={{ position: 'absolute', inset: 0, padding: '0 max(18px,calc((100% - 1080px)/2))' }}>
|
||||
{elements.map((el) => (
|
||||
<HeroElement key={el.id} element={el} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user