ソースを参照

GEM command to generate markup from JSON

Vijayakrishnan Krishnan 4 年 前
コミット
1dcbd6656c

+ 131 - 0
app/Console/Commands/Gem.php

@@ -0,0 +1,131 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class Gem extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'gem
+                            {path:path-in-gem}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    public $output = '';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        global $argv;
+        $in = json_decode(file_get_contents(base_path("gem/forms/{$argv[2]}/spec.json")));
+        $outPath = base_path("gem/forms/{$argv[2]}/build");
+        $this->output = '<div class="gem-nodes">';
+
+        foreach ($in as $node) {
+            $this->output .= $this->gem($node);
+        }
+
+        $this->output .= '</div>';
+
+        file_put_contents(base_path("gem/forms/{$argv[2]}/build/form.blade.php"), $this->output);
+        echo "OK";
+    }
+
+    public function gem($_node, $_parentKey = false, $_level = 0)
+    {
+        $output = '';
+        $key = ($_parentKey ? $_parentKey . '__' : '') . $_node->K;
+
+        // start container
+        $output .= $this->ln('<div ' .
+            'class="my-3 node node-level-' . $_level . '" ' .
+            'data-key="' . $key . '">', $_level + 1);
+
+        // label
+        $output .= $this->ln('<label>' . $_node->Q . '</label>', $_level + 2);
+
+        // input
+        if (!!@$_node->T) {
+            switch ($_node->T) {
+                case 'YNUM':
+                    // start
+                    $output .= $this->ln('<div class="d-flex align-items-center">', $_level + 1);
+
+                    // YES
+                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $_level + 2);
+                    $output .= $this->ln('<input name="' . $key . '" type="radio" value="YES" class="mr-1">', $_level + 3);
+                    $output .= $this->ln('<span>Yes</span>', $_level + 3);
+                    $output .= $this->ln('</label>', $_level + 2);
+
+                    // NO
+                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $_level + 2);
+                    $output .= $this->ln('<input name="' . $key . '" type="radio" value="NO" class="mr-1">', $_level + 3);
+                    $output .= $this->ln('<span>No</span>', $_level + 3);
+                    $output .= $this->ln('</label>', $_level + 2);
+
+                    // NO
+                    $output .= $this->ln('<label class="d-inline-flex align-items-center my-0 mr-3">', $_level + 2);
+                    $output .= $this->ln('<input name="' . $key . '" type="radio" value="UNKNOWN" class="mr-1">', $_level + 3);
+                    $output .= $this->ln('<span>Unknown</span>', $_level + 3);
+                    $output .= $this->ln('</label>', $_level + 2);
+
+                    // MEMO
+                    $output .= $this->ln('<input name="' . $key . '_memo" type="text" class="form-control form-control-sm">', $_level + 2);
+
+                    // end
+                    $output .= $this->ln('</div>', $_level + 1);
+                    break;
+            }
+        }
+
+        // subs
+        if (!!@$_node->S) {
+            $output .= '<div class="subs pl-4">';
+            foreach ($_node->S as $sub) {
+                $output .= $this->gem($sub, $key, $_level + 1);
+            }
+            $output .= '</div>';
+        }
+
+        // close container
+        $output .= $this->ln('</div>', $_level + 1);
+        $output .= $this->nl();
+
+        return $output;
+    }
+
+    public function ln($_line, $_indent = 1, $_nlAfter = true)
+    {
+        return str_repeat(" ", $_indent * 4) . $_line . ($_nlAfter ? "\n" : '');
+    }
+
+    public function nl()
+    {
+        return "\n";
+    }
+
+}

+ 448 - 0
gem/forms/new-patient-intake/build/form.blade.php

@@ -0,0 +1,448 @@
+<div class="gem-nodes">    <div class="my-3 node node-level-0" data-key="blood_ox">
+        <label>Blood Oxygen</label>
+<div class="subs pl-4">        <div class="my-3 node node-level-1" data-key="blood_ox__ever_used_fingertip_meter">
+            <label>Have you ever used a fingertip blood oxygen saturation meter before?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__ever_used_fingertip_meter" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__ever_used_fingertip_meter" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__ever_used_fingertip_meter" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="blood_ox__ever_used_fingertip_meter_memo" type="text" class="form-control form-control-sm">
+        </div>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="blood_ox__ever_used_fingertip_meter__has_one">
+                <label>Do you currently have one at home?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__has_one" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__has_one" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__has_one" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="blood_ox__ever_used_fingertip_meter__has_one_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__ever_used_fingertip_meter__confirmed_will_discontinue_current">
+                <label>If yes, please discontinue use of that when you receive the one we send you.</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__confirmed_will_discontinue_current" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__confirmed_will_discontinue_current" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__ever_used_fingertip_meter__confirmed_will_discontinue_current" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="blood_ox__ever_used_fingertip_meter__confirmed_will_discontinue_current_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="blood_ox__does_pcp_regularly_check">
+            <label>Does your PCP regularly check your resting oxygen saturation?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__does_pcp_regularly_check" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__does_pcp_regularly_check" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__does_pcp_regularly_check" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="blood_ox__does_pcp_regularly_check_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="blood_ox__baseline_resting_spo2_level">
+            <label>Do you know what your baseline resting oxygen saturation usually measures at?</label>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="blood_ox__lung_condition_that_may_affect">
+            <label>Do you have any lung condition, such as asthma or COPD, that might affect the reading when you measure your blood oxygen level?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__lung_condition_that_may_affect" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__lung_condition_that_may_affect" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="blood_ox__lung_condition_that_may_affect" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="blood_ox__lung_condition_that_may_affect_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="blood_ox__o2_and_activity">
+            <label>Blood oxygen values depend a lot on your level of physical activity.</label>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__days_per_week_aerobic_exercise_with_exertion">
+                <label>How many days per week do you currently perform aerobic exercise to the point that you can feel your lungs working harder and your heart beating faster?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__minutes_per_week_aerobic_exercise_with_exertion">
+                <label>How many total minutes per week on average would you say you are in a state of aerobic exercise, where you feel your lungs working harder and your heart beating faster?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__ever_had_o2_checked_before_after_exercise">
+                <label>Have you ever had your oxygen checked before and after exercise?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__ever_had_o2_checked_before_after_exercise" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__ever_had_o2_checked_before_after_exercise" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__ever_had_o2_checked_before_after_exercise" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="blood_ox__o2_and_activity__ever_had_o2_checked_before_after_exercise_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__baseline_o2_assessment">
+                <label>Once you receive the oxygen meter, we will need to call you to make sure you take a proper baseline resting measurement, and then another measurement after you have you walk for 1 minute. When is the best time and number to call usually?</label>
+<div class="subs pl-4">                <div class="my-3 node node-level-3" data-key="blood_ox__o2_and_activity__baseline_o2_assessment__best_time_to_call">
+                    <label>Best time to call:</label>
+                </div>
+
+                <div class="my-3 node node-level-3" data-key="blood_ox__o2_and_activity__baseline_o2_assessment__best_number_to_call">
+                    <label>Best number to call:</label>
+                </div>
+
+</div>            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active">
+                <label>Has the COVID-19 pandemic made you less physically active than you were before?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active">
+                <label>Has the COVID-19 pandemic made you less physically active than you were before?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="blood_ox__o2_and_activity__has_covid_made_you_less_physically_active_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+</div>        </div>
+
+</div>    </div>
+
+    <div class="my-3 node node-level-0" data-key="pulse_and_bp">
+        <label>Pulse & BP</label>
+<div class="subs pl-4">        <div class="my-3 node node-level-1" data-key="pulse_and_bp__ever_used_auto_pulse_bp_meter">
+            <label>Have you ever used an automatic pulse and blood pressure meter before?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter_memo" type="text" class="form-control form-control-sm">
+        </div>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="pulse_and_bp__ever_used_auto_pulse_bp_meter__has_one">
+                <label>Do you currently have one at home?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__has_one" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__has_one" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__has_one" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__has_one_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="pulse_and_bp__ever_used_auto_pulse_bp_meter__confirmed_will_discontinue_current">
+                <label>If yes, please discontinue use of that when you receive the one we send you.</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__confirmed_will_discontinue_current" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__confirmed_will_discontinue_current" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__confirmed_will_discontinue_current" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="pulse_and_bp__ever_used_auto_pulse_bp_meter__confirmed_will_discontinue_current_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="pulse_and_bp__usual_resting_pulse">
+            <label>What is your usual resting pulse?</label>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="pulse_and_bp__usual_resting_bp">
+            <label>What is your usual resting blood pressure?</label>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="pulse_and_bp__usual_resting_bp__systolic">
+                <label>Systolic</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="pulse_and_bp__usual_resting_bp__diastolic">
+                <label>Diastolic</label>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="pulse_and_bp__ever_dx_with_htn">
+            <label>Have you ever been diagnosed with high blood pressure?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_dx_with_htn" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_dx_with_htn" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="pulse_and_bp__ever_dx_with_htn" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="pulse_and_bp__ever_dx_with_htn_memo" type="text" class="form-control form-control-sm">
+        </div>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="pulse_and_bp__ever_dx_with_htn__on_bp_medications">
+                <label>Are you on any BP medication?</label>
+            <div class="d-flex align-items-center">
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_dx_with_htn__on_bp_medications" type="radio" value="YES" class="mr-1">
+                    <span>Yes</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_dx_with_htn__on_bp_medications" type="radio" value="NO" class="mr-1">
+                    <span>No</span>
+                </label>
+                <label class="d-inline-flex align-items-center my-0 mr-3">
+                    <input name="pulse_and_bp__ever_dx_with_htn__on_bp_medications" type="radio" value="UNKNOWN" class="mr-1">
+                    <span>Unknown</span>
+                </label>
+                <input name="pulse_and_bp__ever_dx_with_htn__on_bp_medications_memo" type="text" class="form-control form-control-sm">
+            </div>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="pulse_and_bp__ever_dx_with_htn__who_treats">
+                <label>Who primarily treats your HTN?</label>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="pulse_and_bp__pcp_or_other_doc_bp_target">
+            <label>Has your primary care physician, or another doctor, ever told you what your target BP should be?</label>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="pulse_and_bp__pcp_or_other_doc_bp_target__systolic">
+                <label>Systolic</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="pulse_and_bp__pcp_or_other_doc_bp_target__diastolic">
+                <label>Diastolic</label>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="pulse_and_bp__pulse_during_exercise">
+            <label>When you exercise, what does your pulse reach?</label>
+        </div>
+
+</div>    </div>
+
+    <div class="my-3 node node-level-0" data-key="temp_thermometer">
+        <label>Thermometer / Temp.</label>
+<div class="subs pl-4">        <div class="my-3 node node-level-1" data-key="temp_thermometer__ever_used_itg_before">
+            <label>Have you ever used an infrared temperature gun before?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__ever_used_itg_before" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__ever_used_itg_before" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__ever_used_itg_before" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="temp_thermometer__ever_used_itg_before_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="temp_thermometer__usual_resting_temp">
+            <label>What does your resting temperature usually run at?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__usual_resting_temp" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__usual_resting_temp" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__usual_resting_temp" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="temp_thermometer__usual_resting_temp_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="temp_thermometer__do_you_or_someone_at_home_go_outdoors">
+            <label>Do you or anyone you live with currently go outdoors in public places?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__do_you_or_someone_at_home_go_outdoors" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__do_you_or_someone_at_home_go_outdoors" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__do_you_or_someone_at_home_go_outdoors" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="temp_thermometer__do_you_or_someone_at_home_go_outdoors_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="temp_thermometer__will_you_check_people_temp_before_they_come_near">
+            <label>Can you start to check people's temperature before they come near you?</label>
+        <div class="d-flex align-items-center">
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__will_you_check_people_temp_before_they_come_near" type="radio" value="YES" class="mr-1">
+                <span>Yes</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__will_you_check_people_temp_before_they_come_near" type="radio" value="NO" class="mr-1">
+                <span>No</span>
+            </label>
+            <label class="d-inline-flex align-items-center my-0 mr-3">
+                <input name="temp_thermometer__will_you_check_people_temp_before_they_come_near" type="radio" value="UNKNOWN" class="mr-1">
+                <span>Unknown</span>
+            </label>
+            <input name="temp_thermometer__will_you_check_people_temp_before_they_come_near_memo" type="text" class="form-control form-control-sm">
+        </div>
+        </div>
+
+</div>    </div>
+
+    <div class="my-3 node node-level-0" data-key="bmi">
+        <label>BMI</label>
+<div class="subs pl-4">        <div class="my-3 node node-level-1" data-key="bmi__current">
+            <label>What is your current:</label>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="bmi__current__height_in_inches">
+                <label>Height in inches?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="bmi__current__weight_in_pounds">
+                <label>Weight in pounds?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="bmi__current__waistline_in_inches">
+                <label>Waistline in inches?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="bmi__current__body_fat_percent">
+                <label>Body fat %?</label>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="bmi__at_20_years_old">
+            <label>When you were 20 years old, what was your:</label>
+<div class="subs pl-4">            <div class="my-3 node node-level-2" data-key="bmi__at_20_years_old__weight_in_pounds">
+                <label>Weight in pounds?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="bmi__at_20_years_old__waistline_in_inches">
+                <label>Waistline in inches?</label>
+            </div>
+
+            <div class="my-3 node node-level-2" data-key="bmi__at_20_years_old__height_in_inches">
+                <label>Height in inches?</label>
+            </div>
+
+</div>        </div>
+
+        <div class="my-3 node node-level-1" data-key="bmi__weight_goal_today">
+            <label>Personal weight goal today</label>
+        </div>
+
+        <div class="my-3 node node-level-1" data-key="bmi__barriers_to_exercise">
+            <label>Do you currently have any conditions, such as arthritis or joint pain, that limit your ability to exercise?</label>
+        </div>
+
+</div>    </div>
+
+</div>

+ 261 - 0
gem/forms/new-patient-intake/spec.json

@@ -0,0 +1,261 @@
+[
+    {
+        "Q": "Blood Oxygen",
+        "K": "blood_ox",
+        "S": [
+            {
+                "Q": "Have you ever used a fingertip blood oxygen saturation meter before?",
+                "T": "YNUM",
+                "K": "ever_used_fingertip_meter",
+                "S": [
+                    {
+                        "Q": "Do you currently have one at home?",
+                        "T": "YNUM",
+                        "K": "has_one"
+                    },
+                    {
+                        "Q": "If yes, please discontinue use of that when you receive the one we send you.",
+                        "T": "YNUM",
+                        "K": "confirmed_will_discontinue_current"
+                    }
+                ]
+            },
+            {
+                "Q": "Does your PCP regularly check your resting oxygen saturation?",
+                "T": "YNUM",
+                "K": "does_pcp_regularly_check"
+            },
+            {
+                "Q": "Do you know what your baseline resting oxygen saturation usually measures at?",
+                "T": "SRV",
+                "K": "baseline_resting_spo2_level"
+            },
+            {
+                "Q": "Do you have any lung condition, such as asthma or COPD, that might affect the reading when you measure your blood oxygen level?",
+                "T": "YNUM",
+                "K": "lung_condition_that_may_affect"
+            },
+            {
+                "Q": "Blood oxygen values depend a lot on your level of physical activity.",
+                "K": "o2_and_activity",
+                "S": [
+                    {
+                        "Q": "How many days per week do you currently perform aerobic exercise to the point that you can feel your lungs working harder and your heart beating faster?",
+                        "T": "Text with Memo",
+                        "K": "days_per_week_aerobic_exercise_with_exertion"
+                    },
+                    {
+                        "Q": "How many total minutes per week on average would you say you are in a state of aerobic exercise, where you feel your lungs working harder and your heart beating faster?",
+                        "T": "Text with Memo",
+                        "K": "minutes_per_week_aerobic_exercise_with_exertion"
+                    },
+                    {
+                        "Q": "Have you ever had your oxygen checked before and after exercise?",
+                        "T": "YNUM",
+                        "K": "ever_had_o2_checked_before_after_exercise"
+                    },
+                    {
+                        "Q": "Once you receive the oxygen meter, we will need to call you to make sure you take a proper baseline resting measurement, and then another measurement after you have you walk for 1 minute. When is the best time and number to call usually?",
+                        "T": "Text with Memo",
+                        "K": "baseline_o2_assessment",
+                        "S": [
+                            {
+                                "Q": "Best time to call:",
+                                "T": "Text with Memo",
+                                "K": "best_time_to_call"
+                            },
+                            {
+                                "Q": "Best number to call:",
+                                "T": "Text with Memo",
+                                "K": "best_number_to_call"
+                            }
+                        ]
+                    },
+                    {
+                        "Q": "Has the COVID-19 pandemic made you less physically active than you were before?",
+                        "T": "YNUM",
+                        "K": "has_covid_made_you_less_physically_active"
+                    },
+                    {
+                        "Q": "Has the COVID-19 pandemic made you less physically active than you were before?",
+                        "T": "YNUM",
+                        "K": "has_covid_made_you_less_physically_active"
+                    }
+                ]
+            }
+        ]
+    },
+    {
+        "Q": "Pulse & BP",
+        "K": "pulse_and_bp",
+        "S": [
+            {
+                "Q": "Have you ever used an automatic pulse and blood pressure meter before?",
+                "T": "YNUM",
+                "K": "ever_used_auto_pulse_bp_meter",
+                "S": [
+                    {
+                        "Q": "Do you currently have one at home?",
+                        "T": "YNUM",
+                        "K": "has_one"
+                    },
+                    {
+                        "Q": "If yes, please discontinue use of that when you receive the one we send you.",
+                        "T": "YNUM",
+                        "K": "confirmed_will_discontinue_current"
+                    }
+                ]
+            },
+            {
+                "Q": "What is your usual resting pulse?",
+                "T": "SRV",
+                "K": "usual_resting_pulse"
+            },
+            {
+                "Q": "What is your usual resting blood pressure?",
+                "K": "usual_resting_bp",
+                "S": [
+                    {
+                        "Q": "Systolic",
+                        "T": "SRV",
+                        "K": "systolic"
+                    },
+                    {
+                        "Q": "Diastolic",
+                        "T": "SRV",
+                        "K": "diastolic"
+                    }
+                ]
+            },
+            {
+                "Q": "Have you ever been diagnosed with high blood pressure?",
+                "K": "ever_dx_with_htn",
+                "T": "YNUM",
+                "S": [
+                    {
+                        "Q": "Are you on any BP medication?",
+                        "K": "on_bp_medications",
+                        "T": "YNUM"
+                    },
+                    {
+                        "Q": "Who primarily treats your HTN?",
+                        "K": "who_treats",
+                        "T": "SRV"
+                    }
+                ]
+            },
+            {
+                "Q": "Has your primary care physician, or another doctor, ever told you what your target BP should be?",
+                "K": "pcp_or_other_doc_bp_target",
+                "S": [
+                    {
+                        "Q": "Systolic",
+                        "T": "SRV",
+                        "K": "systolic"
+                    },
+                    {
+                        "Q": "Diastolic",
+                        "T": "SRV",
+                        "K": "diastolic"
+                    }
+                ]
+            },
+            {
+                "Q": "When you exercise, what does your pulse reach?",
+                "K": "pulse_during_exercise",
+                "T": "SRV"
+            }
+        ]
+    },
+    {
+        "Q": "Thermometer / Temp.",
+        "K": "temp_thermometer",
+        "S": [
+            {
+                "Q": "Have you ever used an infrared temperature gun before?",
+                "K": "ever_used_itg_before",
+                "T": "YNUM"
+            },
+            {
+                "Q": "What does your resting temperature usually run at?",
+                "K": "usual_resting_temp",
+                "T": "YNUM"
+            },
+            {
+                "Skip": true,
+                "Q": "Do you or anyone you live with currently go outdoors in public places?",
+                "K": "do_you_or_someone_at_home_go_outdoors",
+                "T": "YNUM"
+            },
+            {
+                "Skip": true,
+                "Q": "Can you start to check people's temperature before they come near you?",
+                "K": "will_you_check_people_temp_before_they_come_near",
+                "T": "YNUM"
+            }
+        ]
+    },
+    {
+        "Q": "BMI",
+        "K": "bmi",
+        "S": [
+            {
+                "Q": "What is your current:",
+                "K": "current",
+                "S": [
+                    {
+                        "Q": "Height in inches?",
+                        "K": "height_in_inches",
+                        "T": "SRV"
+                    },
+                    {
+                        "Q": "Weight in pounds?",
+                        "K": "weight_in_pounds",
+                        "T": "SRV"
+                    },
+                    {
+                        "Q": "Waistline in inches?",
+                        "K": "waistline_in_inches",
+                        "T": "SRV"
+                    },
+                    {
+                        "Q": "Body fat %?",
+                        "K": "body_fat_percent",
+                        "T": "SRV"
+                    }
+                ]
+            },
+            {
+                "Q": "When you were 20 years old, what was your:",
+                "K": "at_20_years_old",
+                "S": [
+                    {
+                        "Q": "Weight in pounds?",
+                        "K": "weight_in_pounds",
+                        "T": "SRV"
+                    },
+                    {
+                        "Q": "Waistline in inches?",
+                        "K": "waistline_in_inches",
+                        "T": "SRV"
+                    },
+                    {
+                        "Q": "Height in inches?",
+                        "K": "height_in_inches",
+                        "T": "SRV"
+                    }
+                ]
+            },
+            {
+                "Q": "Personal weight goal today",
+                "K": "weight_goal_today",
+                "T": "SRV"
+            },
+            {
+                "Q": "Do you currently have any conditions, such as arthritis or joint pain, that limit your ability to exercise?",
+                "K": "barriers_to_exercise",
+                "T": "Text with Memo"
+            }
+        ]
+    }
+]

+ 43 - 0
gem/templates/form.blade.php

@@ -0,0 +1,43 @@
+<?php
+$contentData = false;
+if($section){
+    $contentData = json_decode($section->content_data, true);
+}
+if(!$contentData || !isset($contentData['value'])) {
+    $contentData = [
+        'value'=>''
+    ];
+}
+$formID = rand(0, 100000);
+?>
+<form method="POST" action="/process_form_submit" onsubmit="return submitForm_NoteSection_{{ $formID }}(this);">
+    <?php if($section): ?>
+        <input type="hidden" name="section_uid" value="<?= $section->uid?>">
+    <?php else: ?>
+        <input type="hidden" name="note_uid" value="<?= $note->uid?>">
+        <input type="hidden" name="section_template_uid" value="<?= $sectionTemplate->uid ?>">
+    <?php endif; ?>
+    <div class="form-group mb-2">
+        <textarea rte type="text" class="form-control form-control-sm p-2" name="value" placeholder="Value"><?= $contentData['value'] ?></textarea>
+    </div>
+
+    <!-- __GENERATED_MARKUP__ -->
+
+    <div class="form-group m-0 d-flex">
+        <button class="btn btn-sm btn-primary mr-2">Submit</button>
+        <button class="btn btn-sm btn-default border" onclick="return cancelForm_NoteSection_{{ $formID }}(this)">Cancel</button>
+    </div>
+</form>
+<script>
+    function submitForm_NoteSection_{{ $formID }}(_form) {
+        showMask();
+        $.post(_form.action, $(_form).serialize(), function(_data) {
+            fastReload();
+        });
+        return false;
+    }
+    function cancelForm_NoteSection_{{ $formID }}(_trigger) {
+        $(_trigger).closest('.note-section').toggleClass('edit');
+        return false;
+    }
+</script>

+ 2 - 0
gem/templates/processor.php

@@ -0,0 +1,2 @@
+<?php
+$newContentData = $request->all();

+ 1 - 0
gem/templates/summary.php

@@ -0,0 +1 @@
+<div><?= dump($newContentData['value']) ?></div>

+ 29 - 0
public/css/style.css

@@ -629,3 +629,32 @@ body .break-spaces {
     top: 100%;
     z-index: 1;
 }
+
+.gem-nodes .node {
+    border: 1px solid #ddd;
+    padding: 0.75rem;
+    border-radius: 5px;
+}
+.gem-nodes>.node {
+    border: 0 !important;
+}
+.gem-nodes>.node:first-child {
+    margin-top: 0 !important;
+}
+.gem-nodes>.node>label {
+    font-weight: bold;
+    font-size: 14px;
+    margin: 0;
+}
+.gem-nodes .subs .node:last-child {
+    margin-bottom: 0 !important;
+}
+.gem-nodes>.node>.subs {
+    padding-left: 0 !important;
+}
+.gem-nodes>.node>.subs>.node {
+    background: #f2f2f2;
+}
+.gem-nodes>.node>.subs>.node>.subs>.node {
+    background: #fff;
+}