';
$out .= '' . vs01_h($field['label']) . ' ';
$out .= ' ';
$out .= '';
return $out;
}
function vs01_render_field_number($field, $value = '') {
$id = vs01_h($field['id']);
$out = '
';
$out .= '' . vs01_h($field['label']) . ' ';
$out .= ' ';
$out .= '
';
return $out;
}
function vs01_render_field_date($field, $value = '') {
$id = vs01_h($field['id']);
$out = '';
$out .= '' . vs01_h($field['label']) . ' ';
$out .= ' ';
$out .= '
';
return $out;
}
function vs01_render_field_boolean($field, $value = '') {
$id = vs01_h($field['id']);
$yes = ($value === 'true') ? 'checked' : '';
$no = ($value === 'false') ? 'checked' : '';
$req = !empty($field['required']) ? 'required' : '';
$out = '';
return $out;
}
function vs01_render_field_select($field, $value = '') {
$id = vs01_h($field['id']);
$options = $field['options'] ?? [];
$out = '';
$out .= '' . vs01_h($field['label']) . ' ';
$out .= '';
$out .= '— select — ';
foreach ($options as $opt) {
$v = vs01_h($opt['value']);
$l = vs01_h($opt['label']);
$sel = ($value === $opt['value']) ? 'selected' : '';
$out .= '' . $l . ' ';
}
$out .= '
';
return $out;
}
function vs01_render_field_textarea($field, $value = '') {
$id = vs01_h($field['id']);
$out = '';
$out .= '' . vs01_h($field['label']) . ' ';
$out .= '';
$out .= '
';
return $out;
}
function vs01_render_field_multiselect($field, $value = '') {
$id = vs01_h($field['id']);
$options = $field['options'] ?? [];
$selected = $value ? json_decode($value, true) : [];
if (!is_array($selected)) $selected = [];
$out = '';
return $out;
}
// ----------------------------------------------------------------------------
// FIELD DISPATCHER
// ----------------------------------------------------------------------------
function vs01_render_field($field, $submitted_values = []) {
$id = $field['id'] ?? '';
$type = $field['type'] ?? 'text';
$value = $submitted_values[$id] ?? '';
switch ($type) {
case 'text': $html = vs01_render_field_text($field, $value); break;
case 'number': $html = vs01_render_field_number($field, $value); break;
case 'date': $html = vs01_render_field_date($field, $value); break;
case 'boolean': $html = vs01_render_field_boolean($field, $value); break;
case 'select': $html = vs01_render_field_select($field, $value); break;
case 'textarea': $html = vs01_render_field_textarea($field, $value); break;
case 'multiselect': $html = vs01_render_field_multiselect($field, $value); break;
default:
$html = 'Unknown field type: ' . vs01_h($type) . '
';
}
$html .= vs01_render_diagnostic_flag($field, $value);
return $html;
}
// ----------------------------------------------------------------------------
// CONDITIONAL DISPLAY
// ----------------------------------------------------------------------------
function vs01_wrap_depends_on($field, $html) {
if (empty($field['depends_on'])) return $html;
$dep_field = vs01_h($field['depends_on']['field']);
$dep_value = $field['depends_on']['value'];
$dep_value = is_array($dep_value)
? vs01_h(json_encode($dep_value))
: vs01_h((string) $dep_value);
return ''
. $html .
'
';
}
// ----------------------------------------------------------------------------
// DIAGNOSTIC FLAGS
// ----------------------------------------------------------------------------
function vs01_render_diagnostic_flag($field, $value) {
if (empty($field['diagnostic_flag'])) return '';
$condition = $field['flag_condition'] ?? null;
if ($condition === null) return '';
$triggered = false;
if (is_array($condition)) {
$triggered = in_array($value, $condition);
} elseif (is_bool($condition)) {
$triggered = ($value === ($condition ? 'true' : 'false'));
} else {
$triggered = ($value === (string) $condition);
}
if (!$triggered) return '';
$severity = vs01_flag_severity($field);
$label = vs01_h($field['flag_label'] ?? 'Diagnostic condition');
$note = isset($field['flag_note'])
? '' . vs01_h($field['flag_note']) . '
'
: '';
return '
' . $label . ' ' . $note . '
';
}
function vs01_flag_severity($field) {
$id = $field['id'] ?? '';
if (in_array($id, ['pro_selfdealing_verified', 'pro_standing_verified', 'pro_incumbent_perpetuation_risk'])) {
return 'critical';
}
if (str_starts_with($id, 'pro_')) return 'high';
return 'standard';
}
// ----------------------------------------------------------------------------
// COMPOUND CONDITION BANNERS
// ----------------------------------------------------------------------------
function vs01_render_compound_banners($association_slug) {
// TODO: query stored VS records for this association from orchestrator
// and evaluate the three compound conditions defined in VS-RENDERER-SPEC.md.
// Returns empty string until orchestrator query is implemented.
return '';
}
// ----------------------------------------------------------------------------
// CROSS-VS REFERENCE NOTES
// ----------------------------------------------------------------------------
function vs01_render_cross_reference($vs_code, $label, $association_slug) {
$url = z_root() . '/vs01/' . vs01_h($association_slug) . '/' . vs01_h($vs_code);
return '';
}
// ----------------------------------------------------------------------------
// VERIFICATION SOURCES PANEL
// ----------------------------------------------------------------------------
function vs01_render_verification_sources($meta) {
$sources = $meta['verification_sources'] ?? [];
if (empty($sources)) return '';
$code = vs01_h($meta['code'] ?? 'vs');
$out = '';
$out .= '
Where to verify this
';
$out .= '
';
foreach ($sources as $source) {
$label = vs01_h($source['label'] ?? '');
$url = vs01_h($source['url'] ?? '');
$instruction = vs01_h($source['instruction'] ?? '');
$out .= '
';
$out .= '
' . $label . ' ';
$out .= '
' . $instruction . '
';
$out .= '
';
}
$out .= '
';
return $out;
}
// ----------------------------------------------------------------------------
// PERSPECTIVE NOTE (VS-07 and VS-09 homeowner slot)
// ----------------------------------------------------------------------------
function vs01_render_perspective_note($schema, $perspective_key) {
if ($perspective_key !== 'homeowner') return '';
$code = $schema['_meta']['code'] ?? '';
if (!in_array($code, ['VS-07', 'VS-09'])) return '';
$notes = $schema['_meta']['renderer_notes'] ?? '';
if (!$notes) return '';
return ''
. vs01_h($notes) . '
';
}
// ----------------------------------------------------------------------------
// IMMUTABLE PUBLIC RECORD
// ----------------------------------------------------------------------------
function vs01_public_record_exists($vs_code, $association_slug) {
// TODO: query orchestrator for existing promoted public record
return false;
}
function vs01_render_public_record_readonly($perspective, $values) {
$out = '';
foreach ($perspective['fields'] ?? [] as $field) {
$id = vs01_h($field['id'] ?? '');
$label = vs01_h($field['label'] ?? '');
$value = vs01_h($values[$field['id'] ?? ''] ?? '—');
$out .= '
';
$out .= '' . $label . ' ';
$out .= '' . $value . ' ';
$out .= '
';
}
$out .= '
';
return $out;
}