| {% extends "base.html" %} |
|
|
| {% block title %}TalkToDoc{% endblock %} |
|
|
| {% block body_class %}patient-page{% endblock %} |
| {% block shell_class %}patient-shell{% endblock %} |
|
|
| {% block header %} |
| <div class="app-header"> |
| <div class="brand"> |
| <span class="brand-mark"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/> |
| </svg> |
| </span> |
| <div> |
| <h1>TalkToDoc</h1> |
| <span class="role-tag">Patient</span> |
| </div> |
| </div> |
| <button type="button" class="header-icon-btn" id="open-history-btn" title="Your consultation history" aria-label="Your consultation history"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <circle cx="12" cy="12" r="9"/> |
| <polyline points="12 7 12 12 15 15"/> |
| </svg> |
| </button> |
| </div> |
| {% endblock %} |
|
|
| {% block content %} |
|
|
| <div id="status-banner" role="alert" aria-live="assertive"></div> |
|
|
| |
| <section class="step active" data-step="1"> |
| <div class="hero"> |
| <div class="hero-orb-wrap"> |
| <div class="hero-orb-glow"></div> |
| <div class="hero-orb"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/> |
| </svg> |
| </div> |
| </div> |
| <h2>Hi, how can we help?</h2> |
| <p>Choose your language, then tell us how you're feeling, by typing or speaking.</p> |
| </div> |
|
|
| <div class="card"> |
| <h3>Choose your language</h3> |
| <div class="language-grid" id="language-grid"> |
| {% for lang in languages %} |
| <button type="button" class="language-option" data-language="{{ lang }}" aria-pressed="false"> |
| {{ lang | capitalize }} |
| </button> |
| {% endfor %} |
| </div> |
| </div> |
| <button type="button" class="btn btn-primary" id="to-step-2" disabled>Continue</button> |
|
|
| <div class="card" id="history-card" style="display: none;"> |
| <h3>Your past messages</h3> |
| <div id="history-list"></div> |
| </div> |
| </section> |
|
|
| |
| <section class="step" data-step="2"> |
| <div class="card"> |
| <h2>Describe how you're feeling</h2> |
| <p>Type your message, tap a quick option, or speak it instead.</p> |
|
|
| <div class="chip-row" id="symptom-chips"> |
| <button type="button" class="chip" data-text="I have a headache">Headache</button> |
| <button type="button" class="chip" data-text="I have a fever">Fever</button> |
| <button type="button" class="chip" data-text="I have a stomach ache">Stomach ache</button> |
| <button type="button" class="chip" data-text="I have a cough">Cough</button> |
| <button type="button" class="chip" data-text="I feel dizzy">Dizziness</button> |
| </div> |
|
|
| <div id="input-panel"> |
| <label for="patient-text">Type your message</label> |
| <div class="input-bar"> |
| <textarea id="patient-text" rows="4" placeholder="For example: I have a headache and a fever since yesterday"></textarea> |
| <button type="button" class="mic-inline-btn" id="record-btn" title="Record your voice" aria-label="Record your voice"> |
| <span id="record-icon"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/> |
| <path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/> |
| </svg> |
| </span> |
| </button> |
| </div> |
| <p class="helper-text" id="record-status"></p> |
| </div> |
|
|
| |
| <div class="listening-panel" id="listening-panel" style="display: none;"> |
| <div class="listening-orb-wrap"> |
| <span class="listening-ring"></span> |
| <span class="listening-ring"></span> |
| <span class="listening-ring"></span> |
| <button type="button" class="listening-core" id="stop-recording-btn" title="Stop recording" aria-label="Stop recording"> |
| <svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg> |
| </button> |
| </div> |
| <div class="listening-caption">We're listening<span class="record-timer" id="record-timer"> 0:00</span></div> |
| <p class="helper-text">Tap the button when you're done.</p> |
| </div> |
|
|
| |
| <div class="listening-panel" id="transcribing-panel" style="display: none;"> |
| <div class="spinner" style="width: 32px; height: 32px; border-color: rgba(96,108,56,0.25); border-top-color: var(--color-primary); margin: 0 auto var(--space-3);"></div> |
| <div class="listening-caption">Working out what you said…</div> |
| </div> |
|
|
| |
| <div class="review-panel" id="review-panel" style="display: none;"> |
| <div class="status-banner info"> |
| <svg class="icon-sm" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align: -2px;"><polyline points="20 6 9 17 4 12"/></svg> |
| Here's what we heard, check it over before sending |
| </div> |
| <label for="review-text">Your message</label> |
| <textarea id="review-text" rows="4"></textarea> |
| <div class="btn-row"> |
| <button type="button" class="btn btn-secondary" id="record-again-btn">Record again</button> |
| </div> |
| </div> |
| </div> |
|
|
| <div class="btn-row"> |
| <button type="button" class="btn btn-secondary" id="back-to-step-1">Back</button> |
| <button type="button" class="btn btn-primary" id="submit-input"> |
| <span class="btn-icon"> |
| <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <line x1="22" y1="2" x2="11" y2="13"/> |
| <polygon points="22 2 15 22 11 13 2 9 22 2"/> |
| </svg> |
| </span> |
| <span class="btn-spinner spinner" style="display: none;"></span> |
| <span class="btn-label">Send to provider</span> |
| </button> |
| </div> |
| </section> |
|
|
| |
| <section class="step" data-step="3"> |
| <div class="card"> |
| <h2>Your conversation</h2> |
| <p>Reference number: <span class="interaction-id" id="interaction-id-display"></span></p> |
| <div class="chat-thread" id="chat-thread"> |
| <div class="chat-bubble from-patient"> |
| <span class="chat-label">You</span> |
| <span id="heard-text"></span> |
| </div> |
| </div> |
| </div> |
|
|
| |
| |
| |
| |
| |
| |
| <div class="card" id="waiting-card"> |
| <div class="status-timeline"> |
| <div class="timeline-step done"> |
| <span class="timeline-dot"></span> |
| <span class="timeline-label">Submitted</span> |
| </div> |
| <div class="timeline-connector"></div> |
| <div class="timeline-step current"> |
| <span class="timeline-dot"></span> |
| <span class="timeline-label">Waiting for provider</span> |
| </div> |
| <div class="timeline-connector"></div> |
| <div class="timeline-step"> |
| <span class="timeline-dot"></span> |
| <span class="timeline-label">Response ready</span> |
| </div> |
| </div> |
|
|
| <p class="helper-text">We check automatically every little while, no need to keep this open.</p> |
|
|
| <div class="waiting-note"> |
| <strong>While you wait:</strong> if your symptoms feel severe or are getting worse |
| quickly, please go to the nearest clinic instead of waiting for a reply here. |
| This is general safety guidance, not advice about your specific message. |
| </div> |
|
|
| <button type="button" class="btn btn-secondary" id="check-response-btn"> |
| <span class="btn-spinner spinner" style="display: none;"></span> |
| <span class="btn-label">Check now</span> |
| </button> |
| </div> |
|
|
| <div class="card" id="response-card" style="display: none;"> |
| <h3>Provider's reply</h3> |
| <div class="audio-player"> |
| <audio id="response-audio" preload="metadata"></audio> |
| <div class="audio-player-controls"> |
| <button type="button" class="audio-btn" id="audio-play-btn" aria-label="Play"> |
| <svg class="icon-play" viewBox="0 0 24 24" fill="currentColor"><polygon points="6 3 20 12 6 21 6 3"/></svg> |
| <svg class="icon-pause" viewBox="0 0 24 24" fill="currentColor" style="display: none;"><rect x="5" y="3" width="5" height="18" rx="1"/><rect x="14" y="3" width="5" height="18" rx="1"/></svg> |
| </button> |
| <button type="button" class="audio-btn audio-btn-sm" id="audio-replay-btn" aria-label="Replay from start"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg> |
| </button> |
| <span class="audio-time" id="audio-current-time">0:00</span> |
| <input type="range" class="audio-seek" id="audio-seek" min="0" max="0" value="0" step="0.1" aria-label="Seek audio position"> |
| <span class="audio-time" id="audio-duration">0:00</span> |
| <a class="audio-btn audio-btn-sm" id="audio-download-btn" download="talktodoc-reply.wav" aria-label="Download audio reply" href="#"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg> |
| </a> |
| </div> |
| </div> |
| </div> |
|
|
| <button type="button" class="btn btn-secondary" id="new-conversation-btn">Start a new conversation</button> |
| </section> |
|
|
| |
| |
| |
| <section class="step" data-step="history"> |
| <div class="card"> |
| <h2>Your consultations</h2> |
| <p class="helper-text">Tap any message to reopen it.</p> |
| <div class="filter-chip-row" id="history-filter-chips" role="group" aria-label="Filter by status"> |
| <button type="button" class="filter-chip active" data-filter="all">All</button> |
| <button type="button" class="filter-chip" data-filter="waiting">Waiting for reply</button> |
| <button type="button" class="filter-chip" data-filter="answered">Answered</button> |
| </div> |
| <input type="text" class="search-input" id="history-search" placeholder="Search your messages" aria-label="Search your consultations"> |
| <div id="history-full-list" style="margin-top: var(--space-4);"></div> |
| <div class="empty-state" id="history-empty-state" style="display: none;"> |
| <svg class="empty-state-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg> |
| <p class="empty-state-title" id="history-empty-title"></p> |
| <p class="empty-state-body" id="history-empty-body"></p> |
| </div> |
| </div> |
| <button type="button" class="btn btn-secondary" id="history-back-btn">Back</button> |
| </section> |
|
|
| <div class="nav-link"><a href="/provider">Go to provider view</a></div> |
|
|
| {% endblock %} |
|
|
| {% block scripts %} |
| <script src="{{ url_for('static', filename='js/patient.js') }}"></script> |
| {% endblock %} |
|
|