File size: 2,569 Bytes
16ff49b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// Detective's checklist: the "what do I do next" rail. Four objectives derived
// entirely from game state; the ACCUSE step pulses when the player is ready.
import { useState } from 'preact/hooks'

import { HOT_SUSPICION, useGame } from '../store'
import { Btn } from './components'

function useObjectives() {
  const g = useGame()
  const c = g.case
  const questioned = c.suspects.filter((s) => (g.state.interrogations[s.id] || []).length > 1).length
  const presented = Object.values(g.state.usedEv).some((l) => l.length > 0)
  const crackedAny = Object.values(g.state.cracked).some(Boolean)
  const hot = Object.values(g.state.suspicion).some((v) => v >= HOT_SUSPICION)
  const ready = (questioned >= c.suspects.length && presented && crackedAny) || hot
  return { g, total: c.suspects.length, questioned, presented, crackedAny, ready }
}

function Step({ done, label }: { done: boolean; label: string }) {
  return (
    <div class={'checklist__step' + (done ? ' checklist__step--done' : '')}>
      <span class="checklist__box">{done ? '■' : '□'}</span>
      <span>{label}</span>
    </div>
  )
}

export function Checklist({ slim = false }: { slim?: boolean }) {
  const { g, total, questioned, presented, crackedAny, ready } = useObjectives()
  const doneCount = (questioned >= total ? 1 : 0) + (presented ? 1 : 0) + (crackedAny ? 1 : 0)
  const [open, setOpen] = useState(questioned === 0) // collapse once the player gets going
  const steps = (
    <>
      <Step done={questioned >= total} label={`QUESTION EVERY SUSPECT ${questioned}/${total}`} />
      <Step done={presented} label="PRESENT EVIDENCE" />
      <Step done={crackedAny} label="CRACK A LIE" />
      <Btn
        sm
        variant={ready ? 'ox' : 'ghost'}
        className={ready ? 'accuse-cta--pulse' : undefined}
        style={{ marginTop: 6 }}
        onClick={() => g.nav('accuse')}
      >
        {ready ? '▸ MAKE THE ACCUSATION' : 'Accuse ▸'}
      </Btn>
    </>
  )
  if (!slim) return <div class="checklist">{steps}</div>
  return (
    <div class="checklist checklist--slim">
      <button class="checklist__toggle" onClick={() => setOpen(!open)}>
        <span class="t-label" style={{ color: 'var(--amber-2)' }}>OBJECTIVES {doneCount}/3</span>
        <span class="t-mono dim">{open ? '▾' : '▸'}</span>
      </button>
      {open && <div class="col" style={{ gap: 4, paddingTop: 6 }}>{steps}</div>}
      {!open && ready && (
        <Btn sm variant="ox" className="accuse-cta--pulse" onClick={() => g.nav('accuse')}>▸ ACCUSE</Btn>
      )}
    </div>
  )
}