scribe-widget 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scribe-widget",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "Floating panel widget for medical transcription using eka.scribe",
5
5
  "main": "dist/scribe-widget.umd.js",
6
6
  "module": "dist/scribe-widget.es.js",
package/src/App.tsx CHANGED
@@ -55,6 +55,12 @@ export function App({ config: initialConfig, onClose }: AppProps) {
55
55
  setCredentials(null);
56
56
  }, [reset]);
57
57
 
58
+ // Handle EMR selection
59
+ const handleSelectEMR = useCallback((emrId: string) => {
60
+ console.log('Selected EMR:', emrId);
61
+ // TODO: Handle EMR selection logic
62
+ }, []);
63
+
58
64
  if (isMinimized) {
59
65
  return null;
60
66
  }
@@ -98,7 +104,13 @@ export function App({ config: initialConfig, onClose }: AppProps) {
98
104
  return <ProcessingState />;
99
105
 
100
106
  case 'results':
101
- return result ? <ResultsState result={result} onNewRecording={handleStartNewRecording} /> : null;
107
+ return result ? (
108
+ <ResultsState
109
+ result={result}
110
+ onNewRecording={handleStartNewRecording}
111
+ onSelectEMR={handleSelectEMR}
112
+ />
113
+ ) : null;
102
114
 
103
115
  case 'polling_error':
104
116
  return (
@@ -0,0 +1,50 @@
1
+ interface EMRListStateProps {
2
+ onSelectEMR: (emrId: string) => void;
3
+ onNewRecording: () => void;
4
+ onBack: () => void;
5
+ }
6
+
7
+ const EMR_LIST = [
8
+ { id: 'eka_emr', name: 'Eka EMR', description: 'Eka Care Electronic Medical Records' },
9
+ { id: 'open_emr', name: 'OpenEMR', description: 'Open-source Electronic Health Records' },
10
+ { id: 'open_mrs', name: 'OpenMRS', description: 'Open Medical Record System' },
11
+ ];
12
+
13
+ export function EMRListState({ onSelectEMR, onNewRecording, onBack }: EMRListStateProps) {
14
+ return (
15
+ <div className="emr-list-state">
16
+ <div className="emr-list-header">
17
+ <button className="back-btn" onClick={onBack} title="Back">
18
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
19
+ <path d="M19 12H5M12 19l-7-7 7-7"/>
20
+ </svg>
21
+ </button>
22
+ <span className="emr-list-title">Integrated EMRs</span>
23
+ </div>
24
+
25
+ <div className="emr-list-content">
26
+ {EMR_LIST.map((emr) => (
27
+ <button
28
+ key={emr.id}
29
+ className="emr-item"
30
+ onClick={() => onSelectEMR(emr.id)}
31
+ >
32
+ <div className="emr-item-info">
33
+ <span className="emr-item-name">{emr.name}</span>
34
+ <span className="emr-item-desc">{emr.description}</span>
35
+ </div>
36
+ <svg className="emr-item-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
37
+ <path d="M9 18l6-6-6-6"/>
38
+ </svg>
39
+ </button>
40
+ ))}
41
+ </div>
42
+
43
+ <div className="emr-list-footer">
44
+ <button className="start-new-recording-btn" onClick={onNewRecording}>
45
+ Start New Recording
46
+ </button>
47
+ </div>
48
+ </div>
49
+ );
50
+ }
@@ -1,11 +1,19 @@
1
1
  import { GetSessionStatusResponse } from 'med-scribe-alliance-ts-sdk';
2
2
 
3
+ const EMR_LIST = [
4
+ { id: 'eka_emr', name: 'Eka EMR', description: 'Eka Care Electronic Medical Records' },
5
+ { id: 'open_emr', name: 'OpenEMR', description: 'Open-source Electronic Health Records' },
6
+ { id: 'open_mrs', name: 'OpenMRS', description: 'Open Medical Record System' },
7
+ ];
8
+
3
9
  interface ResultsStateProps {
4
10
  result: GetSessionStatusResponse;
5
11
  onNewRecording: () => void;
12
+ onSelectEMR: (emrId: string) => void;
6
13
  }
7
14
 
8
- export function ResultsState({ result, onNewRecording }: ResultsStateProps) {
15
+ export function ResultsState({ result, onNewRecording, onSelectEMR }: ResultsStateProps) {
16
+ console.log('prescription result - WIDGET', result);
9
17
  return (
10
18
  <div className="results-state">
11
19
  <div className="results-header">
@@ -17,8 +25,27 @@ export function ResultsState({ result, onNewRecording }: ResultsStateProps) {
17
25
  <div className="results-content">
18
26
  <div className="transcript-section">
19
27
  <div className="section-title">Transcript</div>
20
- <div className="transcript-text">
21
- {result.transcript || 'No transcript available.'}
28
+ <div className="transcript-text">{result.transcript || 'No transcript available.'}</div>
29
+ </div>
30
+
31
+ <div className="emr-section">
32
+ <div className="section-title">Integrated EMRs</div>
33
+ <div className="emr-list-inline">
34
+ {EMR_LIST.map((emr) => (
35
+ <button
36
+ key={emr.id}
37
+ className="emr-item"
38
+ onClick={() => onSelectEMR(emr.id)}
39
+ >
40
+ <div className="emr-item-info">
41
+ <span className="emr-item-name">{emr.name}</span>
42
+ <span className="emr-item-desc">{emr.description}</span>
43
+ </div>
44
+ <svg className="emr-item-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
45
+ <path d="M9 18l6-6-6-6"/>
46
+ </svg>
47
+ </button>
48
+ ))}
22
49
  </div>
23
50
  </div>
24
51
  </div>
@@ -18,7 +18,8 @@
18
18
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.05);
19
19
  z-index: 2147483647;
20
20
  overflow: hidden;
21
- min-width: 320px;
21
+ width: 380px;
22
+ max-width: calc(100vw - 40px);
22
23
  }
23
24
 
24
25
  .panel-header {
@@ -545,3 +546,132 @@
545
546
  background: #f3f4f6;
546
547
  color: #374151;
547
548
  }
549
+
550
+ /* EMR Section (inline on results) */
551
+ .emr-section {
552
+ margin-top: 16px;
553
+ padding-top: 16px;
554
+ border-top: 1px solid #e5e7eb;
555
+ }
556
+
557
+ .emr-list-inline {
558
+ display: flex;
559
+ flex-direction: column;
560
+ gap: 8px;
561
+ }
562
+
563
+ /* EMR List State */
564
+ .emr-list-state {
565
+ display: flex;
566
+ flex-direction: column;
567
+ gap: 16px;
568
+ }
569
+
570
+ .emr-list-header {
571
+ display: flex;
572
+ align-items: center;
573
+ gap: 12px;
574
+ }
575
+
576
+ .back-btn {
577
+ background: none;
578
+ border: none;
579
+ cursor: pointer;
580
+ padding: 4px;
581
+ color: #6b7280;
582
+ display: flex;
583
+ align-items: center;
584
+ justify-content: center;
585
+ width: 32px;
586
+ height: 32px;
587
+ border-radius: 6px;
588
+ transition: all 0.2s;
589
+ }
590
+
591
+ .back-btn:hover {
592
+ background: #f3f4f6;
593
+ color: #374151;
594
+ }
595
+
596
+ .back-btn svg {
597
+ width: 20px;
598
+ height: 20px;
599
+ }
600
+
601
+ .emr-list-title {
602
+ font-size: 16px;
603
+ font-weight: 600;
604
+ color: #111827;
605
+ }
606
+
607
+ .emr-list-content {
608
+ display: flex;
609
+ flex-direction: column;
610
+ gap: 8px;
611
+ max-height: 240px;
612
+ overflow-y: auto;
613
+ }
614
+
615
+ .emr-item {
616
+ display: flex;
617
+ align-items: center;
618
+ justify-content: space-between;
619
+ padding: 12px 16px;
620
+ background: #f9fafb;
621
+ border: 1px solid #e5e7eb;
622
+ border-radius: 8px;
623
+ cursor: pointer;
624
+ transition: all 0.2s;
625
+ text-align: left;
626
+ }
627
+
628
+ .emr-item:hover {
629
+ background: #f3f4f6;
630
+ border-color: #d1d5db;
631
+ }
632
+
633
+ .emr-item-info {
634
+ display: flex;
635
+ flex-direction: column;
636
+ gap: 2px;
637
+ }
638
+
639
+ .emr-item-name {
640
+ font-size: 14px;
641
+ font-weight: 500;
642
+ color: #111827;
643
+ }
644
+
645
+ .emr-item-desc {
646
+ font-size: 12px;
647
+ color: #6b7280;
648
+ }
649
+
650
+ .emr-item-arrow {
651
+ width: 20px;
652
+ height: 20px;
653
+ color: #9ca3af;
654
+ flex-shrink: 0;
655
+ }
656
+
657
+ .emr-list-footer {
658
+ padding-top: 12px;
659
+ border-top: 1px solid #e5e7eb;
660
+ }
661
+
662
+ .start-new-recording-btn {
663
+ width: 100%;
664
+ background: #2563eb;
665
+ color: white;
666
+ border: none;
667
+ padding: 12px 20px;
668
+ border-radius: 8px;
669
+ font-size: 14px;
670
+ font-weight: 500;
671
+ cursor: pointer;
672
+ transition: background 0.2s;
673
+ }
674
+
675
+ .start-new-recording-btn:hover {
676
+ background: #1d4ed8;
677
+ }
package/src/types.ts CHANGED
@@ -8,7 +8,8 @@ export type WidgetState =
8
8
  | 'processing'
9
9
  | 'results'
10
10
  | 'error'
11
- | 'polling_error';
11
+ | 'polling_error'
12
+ | 'emr_list';
12
13
 
13
14
  export interface ScribeWidgetConfig {
14
15
  accessToken?: string;