Spaces:
Running
Running
Ryan Christian D. Deniega commited on
Commit ·
f7e9353
1
Parent(s): 376fe09
ux: improve landing — fix step visuals, add try-it teaser input, expand footer with nav links
Browse files- frontend/src/index.css +5 -0
- frontend/src/pages/LandingPage.jsx +234 -60
- frontend/src/pages/VerifyPage.jsx +9 -1
frontend/src/index.css
CHANGED
|
@@ -308,6 +308,11 @@ a.nav-link-item:hover > div {
|
|
| 308 |
.landing-steps {
|
| 309 |
flex-direction: column;
|
| 310 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 311 |
}
|
| 312 |
|
| 313 |
/* ── Verdict breaking-news banner ──────────────────────── */
|
|
|
|
| 308 |
.landing-steps {
|
| 309 |
flex-direction: column;
|
| 310 |
}
|
| 311 |
+
|
| 312 |
+
.footer-grid {
|
| 313 |
+
grid-template-columns: 1fr !important;
|
| 314 |
+
gap: 32px !important;
|
| 315 |
+
}
|
| 316 |
}
|
| 317 |
|
| 318 |
/* ── Verdict breaking-news banner ──────────────────────── */
|
frontend/src/pages/LandingPage.jsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
-
import {
|
| 2 |
-
import {
|
|
|
|
| 3 |
import { PAGE_STYLE } from '../App.jsx'
|
| 4 |
|
| 5 |
/* ─── data ──────────────────────────────────────────────────── */
|
|
@@ -50,11 +51,23 @@ const STEPS = [
|
|
| 50 |
const STATS = [
|
| 51 |
{ value: '70M+', label: 'Filipinos online', sub: 'one of the highest social media usage rates in the world' },
|
| 52 |
{ value: '6×', label: 'faster spread', sub: 'misinformation travels six times faster than verified news' },
|
| 53 |
-
{ value: '
|
| 54 |
]
|
| 55 |
|
| 56 |
/* ─── component ─────────────────────────────────────────────── */
|
| 57 |
export default function LandingPage() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
return (
|
| 59 |
<div style={{ background: 'var(--bg-base)', overflowX: 'hidden' }}>
|
| 60 |
|
|
@@ -367,6 +380,67 @@ export default function LandingPage() {
|
|
| 367 |
</div>
|
| 368 |
</section>
|
| 369 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 370 |
{/* ── How It Works ─────────────────────────────────────── */}
|
| 371 |
<section style={{ borderBottom: '1px solid var(--border)', background: 'var(--bg-surface)' }}>
|
| 372 |
<div style={{ ...PAGE_STYLE, paddingTop: 80, paddingBottom: 80 }}>
|
|
@@ -410,53 +484,61 @@ export default function LandingPage() {
|
|
| 410 |
padding: '0 40px 0 0',
|
| 411 |
borderRight: i < STEPS.length - 1 ? '1px solid var(--border)' : 'none',
|
| 412 |
marginRight: i < STEPS.length - 1 ? 40 : 0,
|
| 413 |
-
paddingBottom: 0,
|
| 414 |
}}
|
| 415 |
>
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
display: 'flex',
|
| 419 |
-
alignItems: 'center',
|
| 420 |
-
gap: 12,
|
| 421 |
-
marginBottom: 24,
|
| 422 |
-
}}
|
| 423 |
-
>
|
| 424 |
-
<span
|
| 425 |
-
style={{
|
| 426 |
-
fontFamily: 'var(--font-mono)',
|
| 427 |
-
fontSize: 'clamp(2rem, 4vw, 3rem)',
|
| 428 |
-
fontWeight: 700,
|
| 429 |
-
color: 'var(--bg-elevated)',
|
| 430 |
-
letterSpacing: '-0.04em',
|
| 431 |
-
lineHeight: 1,
|
| 432 |
-
WebkitTextStroke: '1px var(--border-light)',
|
| 433 |
-
}}
|
| 434 |
-
>
|
| 435 |
-
{num}
|
| 436 |
-
</span>
|
| 437 |
<div
|
| 438 |
style={{
|
| 439 |
-
width:
|
| 440 |
height: 40,
|
| 441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 442 |
}}
|
| 443 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 444 |
<div>
|
| 445 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
style={{
|
| 447 |
fontFamily: 'var(--font-display)',
|
| 448 |
-
fontSize:
|
| 449 |
fontWeight: 700,
|
| 450 |
-
letterSpacing: '0.
|
| 451 |
textTransform: 'uppercase',
|
| 452 |
-
color: 'var(--accent-red)',
|
| 453 |
}}
|
| 454 |
>
|
| 455 |
{label}
|
| 456 |
-
</
|
| 457 |
-
<Icon size={18} strokeWidth={1.5} style={{ color: 'var(--text-secondary)', marginTop: 4 }} />
|
| 458 |
</div>
|
| 459 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 460 |
<p
|
| 461 |
style={{
|
| 462 |
fontFamily: 'var(--font-body)',
|
|
@@ -541,45 +623,137 @@ export default function LandingPage() {
|
|
| 541 |
</section>
|
| 542 |
|
| 543 |
{/* ── Footer ───────────────────────────────────────────── */}
|
| 544 |
-
<footer
|
| 545 |
-
style={{
|
| 546 |
-
borderTop: '1px solid var(--border)',
|
| 547 |
-
background: 'var(--bg-base)',
|
| 548 |
-
}}
|
| 549 |
-
>
|
| 550 |
<div
|
| 551 |
style={{
|
| 552 |
...PAGE_STYLE,
|
| 553 |
-
paddingTop:
|
| 554 |
-
paddingBottom:
|
| 555 |
-
display: '
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
gap: 16,
|
| 560 |
}}
|
|
|
|
| 561 |
>
|
| 562 |
-
|
| 563 |
-
|
|
|
|
| 564 |
fontFamily: 'var(--font-display)',
|
| 565 |
fontSize: 13,
|
| 566 |
fontWeight: 800,
|
| 567 |
letterSpacing: '0.1em',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 568 |
color: 'var(--text-muted)',
|
| 569 |
-
|
| 570 |
-
|
| 571 |
-
|
| 572 |
-
|
| 573 |
-
|
| 574 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 575 |
fontFamily: 'var(--font-mono)',
|
| 576 |
-
fontSize:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 577 |
color: 'var(--text-muted)',
|
| 578 |
letterSpacing: '0.1em',
|
| 579 |
-
}}
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
</
|
| 583 |
</div>
|
| 584 |
</footer>
|
| 585 |
|
|
|
|
| 1 |
+
import { useState } from 'react'
|
| 2 |
+
import { Link, useNavigate } from 'react-router-dom'
|
| 3 |
+
import { FileText, Link2, Image, Video, ArrowRight, Database, ShieldCheck, Github, BookOpen, Clock, TrendingUp } from 'lucide-react'
|
| 4 |
import { PAGE_STYLE } from '../App.jsx'
|
| 5 |
|
| 6 |
/* ─── data ──────────────────────────────────────────────────── */
|
|
|
|
| 51 |
const STATS = [
|
| 52 |
{ value: '70M+', label: 'Filipinos online', sub: 'one of the highest social media usage rates in the world' },
|
| 53 |
{ value: '6×', label: 'faster spread', sub: 'misinformation travels six times faster than verified news' },
|
| 54 |
+
{ value: '3.8B', label: 'fake engagements', sub: 'estimated fake-news interactions on PH social media annually' },
|
| 55 |
]
|
| 56 |
|
| 57 |
/* ─── component ─────────────────────────────────────────────── */
|
| 58 |
export default function LandingPage() {
|
| 59 |
+
const navigate = useNavigate()
|
| 60 |
+
const [tryInput, setTryInput] = useState('')
|
| 61 |
+
|
| 62 |
+
function handleTrySubmit(e) {
|
| 63 |
+
e.preventDefault()
|
| 64 |
+
if (tryInput.trim()) {
|
| 65 |
+
navigate('/verify', { state: { prefill: tryInput.trim() } })
|
| 66 |
+
} else {
|
| 67 |
+
navigate('/verify')
|
| 68 |
+
}
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
return (
|
| 72 |
<div style={{ background: 'var(--bg-base)', overflowX: 'hidden' }}>
|
| 73 |
|
|
|
|
| 380 |
</div>
|
| 381 |
</section>
|
| 382 |
|
| 383 |
+
{/* ── Inline CTA Teaser ─────────────────────────────── */}
|
| 384 |
+
<section style={{ borderBottom: '1px solid var(--border)', background: 'var(--bg-elevated)' }}>
|
| 385 |
+
<div style={{ ...PAGE_STYLE, paddingTop: 48, paddingBottom: 48 }}>
|
| 386 |
+
<p style={{
|
| 387 |
+
fontFamily: 'var(--font-mono)',
|
| 388 |
+
fontSize: 11,
|
| 389 |
+
letterSpacing: '0.2em',
|
| 390 |
+
textTransform: 'uppercase',
|
| 391 |
+
color: 'var(--text-muted)',
|
| 392 |
+
marginBottom: 16,
|
| 393 |
+
}}>
|
| 394 |
+
Try it now — no account needed
|
| 395 |
+
</p>
|
| 396 |
+
<form onSubmit={handleTrySubmit} style={{ display: 'flex', gap: 0, maxWidth: 640 }}>
|
| 397 |
+
<input
|
| 398 |
+
type="text"
|
| 399 |
+
value={tryInput}
|
| 400 |
+
onChange={e => setTryInput(e.target.value)}
|
| 401 |
+
placeholder="Paste any claim, headline, or URL…"
|
| 402 |
+
style={{
|
| 403 |
+
flex: 1,
|
| 404 |
+
background: 'var(--bg-surface)',
|
| 405 |
+
border: '1px solid var(--border)',
|
| 406 |
+
borderRight: 'none',
|
| 407 |
+
color: 'var(--text-primary)',
|
| 408 |
+
fontFamily: 'var(--font-body)',
|
| 409 |
+
fontSize: 15,
|
| 410 |
+
padding: '14px 20px',
|
| 411 |
+
outline: 'none',
|
| 412 |
+
}}
|
| 413 |
+
onFocus={e => e.target.style.borderColor = 'var(--accent-red)'}
|
| 414 |
+
onBlur={e => e.target.style.borderColor = 'var(--border)'}
|
| 415 |
+
/>
|
| 416 |
+
<button
|
| 417 |
+
type="submit"
|
| 418 |
+
style={{
|
| 419 |
+
background: 'var(--accent-red)',
|
| 420 |
+
color: '#fff',
|
| 421 |
+
border: 'none',
|
| 422 |
+
fontFamily: 'var(--font-display)',
|
| 423 |
+
fontSize: 12,
|
| 424 |
+
fontWeight: 700,
|
| 425 |
+
letterSpacing: '0.15em',
|
| 426 |
+
textTransform: 'uppercase',
|
| 427 |
+
padding: '14px 24px',
|
| 428 |
+
cursor: 'pointer',
|
| 429 |
+
display: 'flex',
|
| 430 |
+
alignItems: 'center',
|
| 431 |
+
gap: 8,
|
| 432 |
+
whiteSpace: 'nowrap',
|
| 433 |
+
transition: 'background 0.2s ease-out',
|
| 434 |
+
}}
|
| 435 |
+
onMouseEnter={e => e.currentTarget.style.background = '#b91c1c'}
|
| 436 |
+
onMouseLeave={e => e.currentTarget.style.background = 'var(--accent-red)'}
|
| 437 |
+
>
|
| 438 |
+
Verify <ArrowRight size={14} strokeWidth={2.5} />
|
| 439 |
+
</button>
|
| 440 |
+
</form>
|
| 441 |
+
</div>
|
| 442 |
+
</section>
|
| 443 |
+
|
| 444 |
{/* ── How It Works ─────────────────────────────────────── */}
|
| 445 |
<section style={{ borderBottom: '1px solid var(--border)', background: 'var(--bg-surface)' }}>
|
| 446 |
<div style={{ ...PAGE_STYLE, paddingTop: 80, paddingBottom: 80 }}>
|
|
|
|
| 484 |
padding: '0 40px 0 0',
|
| 485 |
borderRight: i < STEPS.length - 1 ? '1px solid var(--border)' : 'none',
|
| 486 |
marginRight: i < STEPS.length - 1 ? 40 : 0,
|
|
|
|
| 487 |
}}
|
| 488 |
>
|
| 489 |
+
{/* Step number pill */}
|
| 490 |
+
<div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
<div
|
| 492 |
style={{
|
| 493 |
+
width: 40,
|
| 494 |
height: 40,
|
| 495 |
+
borderRadius: 2,
|
| 496 |
+
background: i === 0 ? 'var(--accent-red)' : 'var(--bg-elevated)',
|
| 497 |
+
border: i === 0 ? 'none' : '1px solid var(--border-light)',
|
| 498 |
+
display: 'flex',
|
| 499 |
+
alignItems: 'center',
|
| 500 |
+
justifyContent: 'center',
|
| 501 |
+
flexShrink: 0,
|
| 502 |
}}
|
| 503 |
+
>
|
| 504 |
+
<Icon size={16} strokeWidth={1.8}
|
| 505 |
+
style={{ color: i === 0 ? '#fff' : 'var(--text-secondary)' }}
|
| 506 |
+
/>
|
| 507 |
+
</div>
|
| 508 |
<div>
|
| 509 |
+
<span
|
| 510 |
+
style={{
|
| 511 |
+
fontFamily: 'var(--font-mono)',
|
| 512 |
+
fontSize: 10,
|
| 513 |
+
fontWeight: 700,
|
| 514 |
+
color: 'var(--text-muted)',
|
| 515 |
+
letterSpacing: '0.2em',
|
| 516 |
+
display: 'block',
|
| 517 |
+
}}
|
| 518 |
+
>
|
| 519 |
+
{num}
|
| 520 |
+
</span>
|
| 521 |
+
<span
|
| 522 |
style={{
|
| 523 |
fontFamily: 'var(--font-display)',
|
| 524 |
+
fontSize: 12,
|
| 525 |
fontWeight: 700,
|
| 526 |
+
letterSpacing: '0.2em',
|
| 527 |
textTransform: 'uppercase',
|
| 528 |
+
color: i === 0 ? 'var(--accent-red)' : 'var(--text-primary)',
|
| 529 |
}}
|
| 530 |
>
|
| 531 |
{label}
|
| 532 |
+
</span>
|
|
|
|
| 533 |
</div>
|
| 534 |
</div>
|
| 535 |
+
{/* Connector line under icon for non-last items */}
|
| 536 |
+
<div style={{
|
| 537 |
+
width: 24,
|
| 538 |
+
height: 2,
|
| 539 |
+
background: i === 0 ? 'var(--accent-red)' : 'var(--border)',
|
| 540 |
+
marginBottom: 20,
|
| 541 |
+
}} />
|
| 542 |
<p
|
| 543 |
style={{
|
| 544 |
fontFamily: 'var(--font-body)',
|
|
|
|
| 623 |
</section>
|
| 624 |
|
| 625 |
{/* ── Footer ───────────────────────────────────────────── */}
|
| 626 |
+
<footer style={{ borderTop: '1px solid var(--border)', background: 'var(--bg-base)' }}>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 627 |
<div
|
| 628 |
style={{
|
| 629 |
...PAGE_STYLE,
|
| 630 |
+
paddingTop: 48,
|
| 631 |
+
paddingBottom: 48,
|
| 632 |
+
display: 'grid',
|
| 633 |
+
gridTemplateColumns: 'auto 1fr auto',
|
| 634 |
+
gap: 48,
|
| 635 |
+
alignItems: 'start',
|
|
|
|
| 636 |
}}
|
| 637 |
+
className="footer-grid"
|
| 638 |
>
|
| 639 |
+
{/* Brand */}
|
| 640 |
+
<div>
|
| 641 |
+
<div style={{
|
| 642 |
fontFamily: 'var(--font-display)',
|
| 643 |
fontSize: 13,
|
| 644 |
fontWeight: 800,
|
| 645 |
letterSpacing: '0.1em',
|
| 646 |
+
color: 'var(--text-primary)',
|
| 647 |
+
marginBottom: 8,
|
| 648 |
+
}}>
|
| 649 |
+
PHIL<span style={{ color: 'var(--accent-red)' }}>VERIFY</span>
|
| 650 |
+
</div>
|
| 651 |
+
<div style={{
|
| 652 |
+
fontFamily: 'var(--font-mono)',
|
| 653 |
+
fontSize: 10,
|
| 654 |
color: 'var(--text-muted)',
|
| 655 |
+
letterSpacing: '0.1em',
|
| 656 |
+
lineHeight: 1.6,
|
| 657 |
+
}}>
|
| 658 |
+
ML2 Final Project<br />
|
| 659 |
+
MIT License · {new Date().getFullYear()}
|
| 660 |
+
</div>
|
| 661 |
+
</div>
|
| 662 |
+
|
| 663 |
+
{/* Nav links */}
|
| 664 |
+
<div style={{ display: 'flex', gap: 48, flexWrap: 'wrap' }}>
|
| 665 |
+
<div>
|
| 666 |
+
<div style={{
|
| 667 |
+
fontFamily: 'var(--font-display)',
|
| 668 |
+
fontSize: 10,
|
| 669 |
+
fontWeight: 700,
|
| 670 |
+
letterSpacing: '0.2em',
|
| 671 |
+
textTransform: 'uppercase',
|
| 672 |
+
color: 'var(--text-muted)',
|
| 673 |
+
marginBottom: 12,
|
| 674 |
+
}}>App</div>
|
| 675 |
+
{[
|
| 676 |
+
{ label: 'Verify', to: '/verify', internal: true },
|
| 677 |
+
{ label: 'History', to: '/history', internal: true },
|
| 678 |
+
{ label: 'Trends', to: '/trends', internal: true },
|
| 679 |
+
].map(({ label, to, internal }) => (
|
| 680 |
+
<div key={label} style={{ marginBottom: 8 }}>
|
| 681 |
+
{internal
|
| 682 |
+
? <Link to={to} style={{
|
| 683 |
+
fontFamily: 'var(--font-body)',
|
| 684 |
+
fontSize: 13,
|
| 685 |
+
color: 'var(--text-secondary)',
|
| 686 |
+
textDecoration: 'none',
|
| 687 |
+
transition: 'color 0.15s ease-out',
|
| 688 |
+
}}
|
| 689 |
+
onMouseEnter={e => e.currentTarget.style.color = 'var(--text-primary)'}
|
| 690 |
+
onMouseLeave={e => e.currentTarget.style.color = 'var(--text-secondary)'}
|
| 691 |
+
>{label}</Link>
|
| 692 |
+
: null
|
| 693 |
+
}
|
| 694 |
+
</div>
|
| 695 |
+
))}
|
| 696 |
+
</div>
|
| 697 |
+
<div>
|
| 698 |
+
<div style={{
|
| 699 |
+
fontFamily: 'var(--font-display)',
|
| 700 |
+
fontSize: 10,
|
| 701 |
+
fontWeight: 700,
|
| 702 |
+
letterSpacing: '0.2em',
|
| 703 |
+
textTransform: 'uppercase',
|
| 704 |
+
color: 'var(--text-muted)',
|
| 705 |
+
marginBottom: 12,
|
| 706 |
+
}}>Resources</div>
|
| 707 |
+
{[
|
| 708 |
+
{ label: 'API Docs', href: 'https://semiautomat1c-philverify-api.hf.space/docs' },
|
| 709 |
+
{ label: 'GitHub', href: 'https://github.com/SemiAutomat1c/philverify' },
|
| 710 |
+
].map(({ label, href }) => (
|
| 711 |
+
<div key={label} style={{ marginBottom: 8 }}>
|
| 712 |
+
<a href={href} target="_blank" rel="noopener noreferrer" style={{
|
| 713 |
+
fontFamily: 'var(--font-body)',
|
| 714 |
+
fontSize: 13,
|
| 715 |
+
color: 'var(--text-secondary)',
|
| 716 |
+
textDecoration: 'none',
|
| 717 |
+
transition: 'color 0.15s ease-out',
|
| 718 |
+
}}
|
| 719 |
+
onMouseEnter={e => e.currentTarget.style.color = 'var(--text-primary)'}
|
| 720 |
+
onMouseLeave={e => e.currentTarget.style.color = 'var(--text-secondary)'}
|
| 721 |
+
>{label}</a>
|
| 722 |
+
</div>
|
| 723 |
+
))}
|
| 724 |
+
</div>
|
| 725 |
+
</div>
|
| 726 |
+
|
| 727 |
+
{/* Disclaimer */}
|
| 728 |
+
<div style={{ maxWidth: 220 }}>
|
| 729 |
+
<div style={{
|
| 730 |
fontFamily: 'var(--font-mono)',
|
| 731 |
+
fontSize: 10,
|
| 732 |
+
color: 'var(--text-muted)',
|
| 733 |
+
lineHeight: 1.6,
|
| 734 |
+
letterSpacing: '0.03em',
|
| 735 |
+
}}>
|
| 736 |
+
For research and educational purposes only. Use responsibly when verifying information on social media.
|
| 737 |
+
</div>
|
| 738 |
+
</div>
|
| 739 |
+
</div>
|
| 740 |
+
|
| 741 |
+
{/* Bottom rule */}
|
| 742 |
+
<div style={{ borderTop: '1px solid var(--border)' }}>
|
| 743 |
+
<div style={{
|
| 744 |
+
...PAGE_STYLE,
|
| 745 |
+
paddingTop: 16,
|
| 746 |
+
paddingBottom: 16,
|
| 747 |
+
}}>
|
| 748 |
+
<span style={{
|
| 749 |
+
fontFamily: 'var(--font-mono)',
|
| 750 |
+
fontSize: 10,
|
| 751 |
color: 'var(--text-muted)',
|
| 752 |
letterSpacing: '0.1em',
|
| 753 |
+
}}>
|
| 754 |
+
Built with FastAPI · React · Whisper · Tesseract · NewsAPI
|
| 755 |
+
</span>
|
| 756 |
+
</div>
|
| 757 |
</div>
|
| 758 |
</footer>
|
| 759 |
|
frontend/src/pages/VerifyPage.jsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
| 1 |
import { useState, useRef, useId, useCallback, useEffect } from 'react'
|
|
|
|
| 2 |
import { api } from '../api'
|
| 3 |
import { scoreColor, VERDICT_MAP, scoreInterpretation, mlConfidenceExplanation, evidenceExplanation } from '../utils/format.js'
|
| 4 |
import { PAGE_STYLE } from '../App.jsx'
|
|
@@ -233,9 +234,16 @@ function saveState(state) {
|
|
| 233 |
/* ── Main Page ──────────────────────────────────────────── */
|
| 234 |
export default function VerifyPage() {
|
| 235 |
const persisted = loadPersistedState()
|
|
|
|
|
|
|
| 236 |
|
| 237 |
const [tab, setTab] = useState(persisted?.tab ?? 'text')
|
| 238 |
-
const [input, setInput] = useState(persisted?.input ?? '')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
const [file, setFile] = useState(null)
|
| 240 |
const [fileObjectUrl, setFileObjectUrl] = useState(null)
|
| 241 |
const [dragOver, setDragOver] = useState(false)
|
|
|
|
| 1 |
import { useState, useRef, useId, useCallback, useEffect } from 'react'
|
| 2 |
+
import { useLocation } from 'react-router-dom'
|
| 3 |
import { api } from '../api'
|
| 4 |
import { scoreColor, VERDICT_MAP, scoreInterpretation, mlConfidenceExplanation, evidenceExplanation } from '../utils/format.js'
|
| 5 |
import { PAGE_STYLE } from '../App.jsx'
|
|
|
|
| 234 |
/* ── Main Page ──────────────────────────────────────────── */
|
| 235 |
export default function VerifyPage() {
|
| 236 |
const persisted = loadPersistedState()
|
| 237 |
+
const location = useLocation()
|
| 238 |
+
const prefill = location.state?.prefill ?? null
|
| 239 |
|
| 240 |
const [tab, setTab] = useState(persisted?.tab ?? 'text')
|
| 241 |
+
const [input, setInput] = useState(prefill ?? persisted?.input ?? '')
|
| 242 |
+
|
| 243 |
+
// Clear navigation state so refresh doesn't re-prefill
|
| 244 |
+
useEffect(() => {
|
| 245 |
+
if (prefill) window.history.replaceState({}, '')
|
| 246 |
+
}, [prefill])
|
| 247 |
const [file, setFile] = useState(null)
|
| 248 |
const [fileObjectUrl, setFileObjectUrl] = useState(null)
|
| 249 |
const [dragOver, setDragOver] = useState(false)
|