File size: 4,772 Bytes
796c5f4
 
572e624
796c5f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
572e624
 
 
 
796c5f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import React from 'react';
import { THEME, tempColor, pHColor, saltColor } from '../theme.js';
import { MediaConfBar, OxygenConfArc, IntervalBar, MonoTag, SourceBadge } from './Primitives.jsx';

export default function DetailDrawer({ microbe, onClose }) {
  if (!microbe) return null;
  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, background: 'rgba(31,29,24,0.4)', zIndex: 50,
      display: 'flex', justifyContent: 'flex-end',
    }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        width: 520, maxWidth: '100%', height: '100%', background: THEME.paper,
        borderLeft: `1px solid ${THEME.ink}`, padding: '20px 24px', overflow: 'auto',
        boxShadow: '-12px 0 24px rgba(0,0,0,0.08)',
      }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 16 }}>
          <div>
            <div style={{ font: `400 11px ${THEME.mono}`, color: THEME.inkFaint, marginBottom: 4 }}>
              {microbe.accession} · CheckM {microbe.completeness.toFixed(1)}%
            </div>
            <div style={{ font: `500 17px ${THEME.serif}`, fontStyle: 'italic', color: THEME.ink, lineHeight: 1.3 }}>
              {microbe.name}
            </div>
            <div style={{ font: `400 12px ${THEME.font}`, color: THEME.inkSoft, marginTop: 4 }}>
              {microbe.phylum}
            </div>
          </div>
          <button onClick={onClose} style={{ border: 'none', background: 'transparent', font: `400 18px ${THEME.mono}`, color: THEME.inkSoft, cursor: 'pointer' }}>×</button>
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, marginBottom: 18 }}>
          <PhenoCell label="T_opt" value={microbe.T_opt} unit="°C" color={tempColor(microbe.T_opt)} scaleMin={0} scaleMax={110} />
          <PhenoCell label="pH" value={microbe.pH} color={pHColor(microbe.pH)} scaleMin={2} scaleMax={11} />
          <PhenoCell label="salt" value={microbe.salt} unit="%" color={saltColor(microbe.salt)} scaleMin={0} scaleMax={25} />
          <div style={{ border: `1px solid ${THEME.rule}`, padding: '10px 12px' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 }}>
              <span style={{ font: `400 10px ${THEME.mono}`, color: THEME.inkFaint, textTransform: 'uppercase', letterSpacing: '0.05em' }}>Oxygen</span>
              <SourceBadge source={microbe.O2_source} compact />
            </div>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
              <OxygenConfArc value={microbe.O2_conf} size={36} />
              <div style={{ font: `500 14px ${THEME.font}`, color: THEME.ink }}>{microbe.O2}</div>
            </div>
          </div>
        </div>

        <div style={{ font: `500 11px ${THEME.mono}`, color: THEME.inkSoft, letterSpacing: '0.08em', textTransform: 'uppercase', marginBottom: 8 }}>
          Top media to try
        </div>
        {[
          { id: microbe.top_medium_id, name: microbe.top_medium_name, conf: microbe.top_confidence },
          { id: microbe.top2_medium_id, name: microbe.top2_medium_name, conf: microbe.top2_confidence },
          { id: microbe.top3_medium_id, name: microbe.top3_medium_name, conf: microbe.top3_confidence },
        ].filter((x) => x.id).map((m, i) => (
          <div key={m.id} style={{
            border: `1px solid ${i === 0 ? THEME.accent : THEME.rule}`,
            padding: '12px 14px',
            background: i === 0 ? '#fdf6e8' : THEME.paper,
            marginBottom: 8, borderRadius: 2,
          }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <MonoTag>{m.id}</MonoTag>
              <span style={{ font: `500 13px ${THEME.font}`, color: THEME.ink, flex: 1 }}>{m.name}</span>
              <MediaConfBar value={m.conf} />
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

function PhenoCell({ label, value, unit = '', color, scaleMin, scaleMax }) {
  return (
    <div style={{ border: `1px solid ${THEME.rule}`, padding: '10px 12px' }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 6 }}>
        <span style={{ font: `400 10px ${THEME.mono}`, color: THEME.inkFaint, textTransform: 'uppercase', letterSpacing: '0.05em' }}>{label}</span>
        <span style={{ font: `500 17px ${THEME.serif}`, color: THEME.ink, fontVariantNumeric: 'tabular-nums' }}>{value}{unit}</span>
      </div>
      <IntervalBar value={value} lo={Math.max(scaleMin, value - (scaleMax - scaleMin) * 0.05)} hi={Math.min(scaleMax, value + (scaleMax - scaleMin) * 0.05)} scaleMin={scaleMin} scaleMax={scaleMax} color={color} height={5} />
    </div>
  );
}