Files
admin.derez.ai/index.html
T
2026-06-16 07:45:26 -03:00

1496 lines
72 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>derez.ai — Admin</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="layout">
<!-- ═══ SIDEBAR ════════════════════════════════════════════════ -->
<nav class="sidebar">
<div class="sidebar-brand">
<svg
width="22"
height="22"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="3" width="20" height="14" rx="2" />
<path d="M8 21h8M12 17v4" />
</svg>
derez.ai
</div>
<div class="sidebar-section-label">Network</div>
<div class="nav-item active" data-section="dns">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<ellipse cx="12" cy="5" rx="9" ry="3" />
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
<path d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3" />
</svg>
DNS Records
</div>
<div class="sidebar-section-label">Infrastructure</div>
<div class="nav-item" data-section="instances">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
<line x1="12" y1="22.08" x2="12" y2="12" />
</svg>
Instances
</div>
<div class="nav-item" data-section="backup">
<svg
width="16"
height="16"
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="17 8 12 3 7 8" />
<line x1="12" y1="3" x2="12" y2="15" />
</svg>
Backup
</div>
<div class="nav-item" data-section="keys">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"
/>
</svg>
Keys
</div>
<div
class="sidebar-section-label"
style="
margin-top: 28px;
padding-top: 12px;
border-top: 1px solid var(--border);
"
>
Dashboards
</div>
<div class="nav-item" data-section="crm">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
<circle cx="9" cy="7" r="4" />
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
</svg>
CRM
</div>
<div class="nav-item" data-section="sales">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="3" y="3" width="7" height="7" />
<rect x="14" y="3" width="7" height="7" />
<rect x="14" y="14" width="7" height="7" />
<rect x="3" y="14" width="7" height="7" />
</svg>
Sales
</div>
<div class="nav-item" data-section="servers">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="2" width="20" height="8" rx="2" />
<rect x="2" y="14" width="20" height="8" rx="2" />
<line x1="6" y1="6" x2="6.01" y2="6" />
<line x1="6" y1="18" x2="6.01" y2="18" />
</svg>
Servers
</div>
<div class="sidebar-footer">
<div
class="nav-item"
id="sidebar-user"
style="
cursor: default;
gap: 8px;
padding: 9px 18px;
border-left: none;
color: var(--text-muted);
font-size: 12px;
"
>
<svg
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"
/>
<circle cx="12" cy="7" r="4" />
</svg>
<span id="sidebar-username">Not signed in</span>
</div>
<div
class="nav-item"
onclick="doSignOut()"
style="
color: var(--danger);
border-left: none;
padding: 9px 0;
"
>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
<polyline points="16 17 21 12 16 7" />
<line x1="21" y1="12" x2="9" y2="12" />
</svg>
Sign Out
</div>
</div>
</nav>
<!-- ═══ MAIN ════════════════════════════════════════════════════ -->
<div class="main">
<!-- Top bar -->
<div class="topbar">
<span class="topbar-title" id="page-title"
>DNS Records</span
>
<div class="topbar-actions" id="topbar-actions">
<button
class="btn btn-ghost btn-sm"
id="btn-refresh"
onclick="dnsLoadRecords()"
>
<svg
width="13"
height="13"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M23 4v6h-6" />
<path d="M1 20v-6h6" />
<path
d="M3.51 9a9 9 0 0 1 14.36-3.36L23 10M1 14l5.13 4.36A9 9 0 0 0 20.49 15"
/>
</svg>
Refresh
</button>
</div>
</div>
<!-- Content -->
<div class="content">
<!-- ─── DNS Section ───────────────────────────────────────── -->
<div class="section active" id="section-dns">
<!-- Filter / search bar -->
<div
class="card"
style="padding: 14px 20px; margin-bottom: 16px"
>
<div
class="form-row"
style="
flex-wrap: nowrap;
gap: 10px;
align-items: center;
"
>
<div
class="form-group"
style="flex: 2; min-width: 140px"
>
<input
type="text"
id="dns-search"
placeholder="Search by name or content…"
oninput="dnsRender()"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 110px"
>
<select
id="dns-filter-type"
onchange="dnsRender()"
>
<option value="">All types</option>
<option selected>A</option>
<option>AAAA</option>
<option>CNAME</option>
<option>MX</option>
<option>TXT</option>
<option>NS</option>
<option>SRV</option>
</select>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-title">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<ellipse cx="12" cy="5" rx="9" ry="3" />
<path
d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"
/>
<path
d="M3 12c0 1.66 4 3 9 3s9-1.34 9-3"
/>
</svg>
Records
</span>
<span
id="dns-record-count"
class="text-muted"
style="font-size: 12px"
></span>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Content</th>
<th>TTL</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="dns-table-body">
<tr>
<td colspan="6">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">
Loading records…
</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- ─── Add New Record ───────────────────────────────────── -->
<div class="card" id="dns-add-card">
<div
class="card-header"
style="margin-bottom: 14px"
>
<span class="card-title">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<circle cx="12" cy="12" r="10" />
<line x1="12" y1="8" x2="12" y2="16" />
<line x1="8" y1="12" x2="16" y2="12" />
</svg>
Add New Record
</span>
</div>
<div class="form-row">
<div
class="form-group"
style="flex: 2; min-width: 140px"
>
<label
>Name
<span style="color: var(--text-muted)"
>(@ for root)</span
></label
>
<input
type="text"
id="add-name"
placeholder="e.g. www"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 100px"
>
<label>Type</label>
<select id="add-type">
<option>A</option>
<option>AAAA</option>
<option>CNAME</option>
<option>MX</option>
<option>TXT</option>
<option>NS</option>
<option>SRV</option>
<option>CAA</option>
</select>
</div>
<div
class="form-group"
style="flex: 3; min-width: 180px"
>
<label>Content</label>
<input
type="text"
id="add-content"
placeholder="e.g. 1.2.3.4 or target.domain.com."
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 100px"
>
<label>TTL (s)</label>
<input
type="number"
id="add-ttl"
value="3600"
min="60"
/>
</div>
<div
class="form-group"
style="
flex: 0 0 auto;
justify-content: flex-end;
"
>
<label style="visibility: hidden"
>Add</label
>
<button
class="btn btn-primary"
id="add-submit-btn"
onclick="dnsAddRecord()"
>
<svg
width="14"
height="14"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="20 6 9 17 4 12" />
</svg>
Add Record
</button>
</div>
</div>
</div>
</div>
<!-- ─── Instances Section ──────────────────────────────────── -->
<div class="section" id="section-instances">
<!-- Search bar -->
<div
class="card"
style="padding: 14px 20px; margin-bottom: 16px"
>
<div
class="form-row"
style="
flex-wrap: nowrap;
gap: 10px;
align-items: center;
"
>
<div
class="form-group"
style="flex: 1; min-width: 140px"
>
<input
type="text"
id="inst-search"
placeholder="Search by agent, domain, UUID or server…"
oninput="instancesRender()"
/>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-title">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
/>
<polyline
points="3.27 6.96 12 12.01 20.73 6.96"
/>
<line
x1="12"
y1="22.08"
x2="12"
y2="12"
/>
</svg>
Instances
</span>
<span
id="inst-record-count"
class="text-muted"
style="font-size: 12px"
></span>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>UUID</th>
<th>Agent</th>
<th>Product</th>
<th>Server</th>
<th>Email</th>
<th>Period</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="inst-table-body">
<tr>
<td colspan="8">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">
Loading instances…
</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ─── Backup Section ─────────────────────────────────────── -->
<div class="section" id="section-backup">
<!-- Search bar -->
<div
class="card"
style="padding: 14px 20px; margin-bottom: 16px"
>
<div
class="form-row"
style="
flex-wrap: nowrap;
gap: 10px;
align-items: center;
"
>
<div
class="form-group"
style="flex: 1; min-width: 140px"
>
<input
type="text"
id="backup-search"
placeholder="Search by name or ID…"
oninput="backupRender()"
/>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-title">
<svg
width="16"
height="16"
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="17 8 12 3 7 8" />
<line x1="12" y1="3" x2="12" y2="15" />
</svg>
Repositories
</span>
<span
id="backup-record-count"
class="text-muted"
style="font-size: 12px"
></span>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Name</th>
<th>ID</th>
<th>Region</th>
<th style="text-align: right">
Size
</th>
<th>Last Modified</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="backup-table-body">
<tr>
<td colspan="7">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">
Loading repositories…
</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ─── Keys Section ───────────────────────────────────── -->
<div class="section" id="section-keys">
<div class="card">
<div class="card-header">
<span class="card-title">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"
/>
</svg>
API Keys
</span>
<span
id="keys-record-count"
class="text-muted"
style="font-size: 12px"
></span>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Name</th>
<th>Key</th>
<th>Status</th>
<th>Limit</th>
<th>Remaining</th>
<th>Reset</th>
<th>Usage (monthly)</th>
<th>Created</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="keys-table-body">
<tr>
<td colspan="9">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">
Loading keys…
</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ─── CRM Section ─────────────────────────── -->
<div class="section" id="section-crm">
<!-- Action bar -->
<div
class="card"
style="padding: 10px 20px; margin-bottom: 16px"
>
<div
class="form-row"
style="
flex-wrap: wrap;
gap: 8px;
align-items: center;
"
>
<div class="form-group" style="flex: 0 0 auto">
<button
class="btn btn-sm"
id="crm-hold-btn"
onclick="crmSetStageSelected('Hold')"
disabled
style="
white-space: nowrap;
background: var(--accent-dim);
color: var(--accent);
border: 1px solid var(--border-hi);
"
>
Set Hold
</button>
</div>
<div class="form-group" style="flex: 0 0 auto">
<button
class="btn btn-sm"
id="crm-active-btn"
onclick="crmSetStageSelected('Active')"
disabled
style="
white-space: nowrap;
background: var(--accent-dim);
color: var(--accent);
border: 1px solid var(--border-hi);
"
>
Set Active
</button>
</div>
<div class="form-group" style="flex: 0 0 auto">
<button
class="btn btn-danger btn-sm"
id="crm-delete-selected-btn"
onclick="crmDeleteSelected()"
disabled
style="white-space: nowrap"
>
<svg
width="12"
height="12"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="3 6 5 6 21 6" />
<path
d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"
/>
<path d="M10 11v6M14 11v6" />
<path
d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"
/>
</svg>
Delete Checked
</button>
</div>
<div
class="form-group"
style="
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 4px;
"
id="crm-category-counts"
></div>
<span style="flex: 1; min-width: 0"></span>
</div>
</div>
<div class="card">
<div class="card-header">
<span class="card-title">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"
/>
<circle cx="9" cy="7" r="4" />
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
</svg>
CRM Contacts
</span>
<span
id="crm-record-count"
class="text-muted"
style="font-size: 12px"
></span>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th style="width: 36px">
<input
type="checkbox"
id="crm-check-all"
onchange="crmToggleAll()"
title="Select / deselect all"
/>
</th>
<th
onclick="crmToggleSort('Name')"
style="
cursor: pointer;
user-select: none;
"
>
Name
<span
class="sort-arrow"
data-sort="Name"
></span>
</th>
<th
onclick="
crmToggleSort('Company')
"
style="
cursor: pointer;
user-select: none;
"
>
Company
<span
class="sort-arrow"
data-sort="Company"
></span>
</th>
<th
onclick="crmToggleSort('email')"
style="
cursor: pointer;
user-select: none;
"
>
Email
<span
class="sort-arrow"
data-sort="email"
></span>
</th>
<th
onclick="crmToggleSort('Stage')"
style="
cursor: pointer;
user-select: none;
"
>
Stage
<span
class="sort-arrow"
data-sort="Stage"
></span>
</th>
<th
onclick="
crmToggleSort('strategy')
"
style="
cursor: pointer;
user-select: none;
"
>
Strategy
<span
class="sort-arrow"
data-sort="strategy"
></span>
</th>
<th
onclick="
crmToggleSort('category')
"
style="
cursor: pointer;
user-select: none;
"
>
Category
<span
class="sort-arrow"
data-sort="category"
></span>
</th>
<th
onclick="
crmToggleSort('affiliate')
"
style="
cursor: pointer;
user-select: none;
"
>
Referral
<span
class="sort-arrow"
data-sort="affiliate"
></span>
</th>
<th
onclick="
crmToggleSort(
'date_next_contact',
)
"
style="
cursor: pointer;
user-select: none;
"
>
Date Next Contact
<span
class="sort-arrow"
data-sort="date_next_contact"
></span>
</th>
</tr>
</thead>
<tr class="crm-search-row">
<th></th>
<th>
<input
type="text"
id="crm-search-name"
placeholder="Filter Name…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th>
<input
type="text"
id="crm-search-company"
placeholder="Filter Company…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th>
<input
type="text"
id="crm-search-email"
placeholder="Filter Email…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th>
<input
type="text"
id="crm-search-stage"
placeholder="Filter Stage…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th>
<input
type="text"
id="crm-search-strategy"
placeholder="Filter Strategy…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th>
<input
type="text"
id="crm-search-category"
placeholder="Filter Category…"
oninput="crmRender()"
class="crm-filter-input"
/>
</th>
<th style="white-space: nowrap">
<input
type="text"
id="crm-search-affiliate"
placeholder="Filter Referral…"
oninput="crmRender()"
class="crm-filter-input"
/>
<button
class="btn btn-ghost btn-sm"
onclick="crmClearFilters()"
title="Clear all filters"
>
</button>
</th>
</tr>
<tbody id="crm-table-body">
<tr>
<td colspan="9">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">
Loading contacts…
</p>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!-- ─── Sales Dashboard ─────────────────────────── -->
<div class="section" id="section-sales">
<div class="card">
<div class="card-header">
<span class="card-title">Sales Dashboard</span>
</div>
<div style="padding: 16px 0 0">
<iframe
src="https://derez.ai/operations.html"
style="
width: 100%;
height: 80vh;
border: none;
border-radius: 6px;
background: #fff;
"
title="Sales Dashboard"
allow="clipboard-read; clipboard-write"
></iframe>
<p
style="
font-size: 12px;
color: var(--text-muted);
margin-top: 10px;
text-align: center;
"
>
<a
href="https://derez.ai/operations.html"
target="_blank"
style="color: var(--accent)"
>
Open in new tab ↗
</a>
</p>
</div>
</div>
</div>
<div class="section" id="section-servers">
<div id="server-tabs-strip" class="server-tabs"></div>
<div id="server-dashboard">
<div class="empty-state">
<div class="spinner"></div>
<p style="margin-top: 12px">Loading servers…</p>
</div>
</div>
</div>
</div>
<!-- /content -->
</div>
<!-- /main -->
</div>
<!-- /layout -->
<!-- ═══ INSTANCES EDIT MODAL ═════════════════════════════════ -->
<div class="modal-backdrop" id="inst-edit-backdrop">
<div class="modal">
<div class="modal-header">
<span class="modal-title">Edit Instance</span>
<button
class="modal-close"
onclick="instancesCloseEdit()"
aria-label="Close"
>
&#x2715;
</button>
</div>
<div class="modal-body">
<div class="form-row" style="flex-wrap: wrap">
<div class="form-group" style="flex: 0 0 100%">
<label
>UUID
<span class="text-muted"
>(read-only)</span
></label
>
<input
type="text"
id="inst-edit-uuid"
disabled
style="opacity: 0.5; cursor: not-allowed"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 120px"
>
<label
>Agent
<span class="text-muted"
>(read-only)</span
></label
>
<input
type="text"
id="inst-edit-agent"
disabled
style="opacity: 0.5; cursor: not-allowed"
/>
</div>
<div
class="form-group"
style="flex: 2; min-width: 200px"
>
<label
>Domain
<span class="text-muted"
>(read-only)</span
></label
>
<input
type="text"
id="inst-edit-domain"
disabled
style="opacity: 0.5; cursor: not-allowed"
/>
</div>
</div>
<hr class="sep" />
<div class="form-row" style="flex-wrap: wrap">
<div
class="form-group"
style="flex: 1; min-width: 110px"
>
<label>SSH Port</label>
<input
type="text"
id="inst-edit-ssh-port"
placeholder="e.g. 22"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 110px"
>
<label>RAM</label>
<input
type="text"
id="inst-edit-ram"
placeholder="e.g. 512m"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 110px"
>
<label>CPU</label>
<input
type="text"
id="inst-edit-cpu"
placeholder="e.g. 2"
/>
</div>
</div>
</div>
<div class="modal-footer">
<button
class="btn btn-ghost"
onclick="instancesCloseEdit()"
>
Cancel
</button>
<button
class="btn btn-primary"
id="inst-save-btn"
onclick="instancesSaveEdit()"
>
<svg
width="13"
height="13"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="20 6 9 17 4 12" />
</svg>
Save Changes
</button>
</div>
</div>
</div>
<!-- ═══ CRM EDIT MODAL ════════════════════════════════════ -->
<div class="modal-backdrop" id="crm-edit-backdrop">
<div class="modal" style="max-width: 640px">
<div class="modal-header">
<span class="modal-title" id="crm-edit-title"
>Edit Contact</span
>
<button
class="modal-close"
onclick="crmCloseEdit()"
aria-label="Close"
>
&#x2715;
</button>
</div>
<div class="modal-body">
<input type="hidden" id="crm-edit-id" />
<div class="form-row" style="flex-wrap: wrap">
<div
class="form-group"
style="flex: 1; min-width: 160px"
>
<label>Name</label>
<input
type="text"
id="crm-edit-name"
placeholder="Contact name"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 160px"
>
<label>Company</label>
<input
type="text"
id="crm-edit-company"
placeholder="Company"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 200px"
>
<label>Email</label>
<input
type="email"
id="crm-edit-email"
placeholder="email@example.com"
/>
</div>
</div>
<div class="form-row" style="flex-wrap: wrap">
<div
class="form-group"
style="flex: 1; min-width: 120px"
>
<label>Stage</label>
<select id="crm-edit-stage">
<option value="">— Select —</option>
<option>Active</option>
<option>Hold</option>
<option>Blacklist</option>
<option>Won</option>
<option>Lost</option>
<option>Contacted</option>
<option>Cold</option>
<option>Warm</option>
<option>Bounced</option>
</select>
</div>
<div
class="form-group"
style="flex: 1; min-width: 160px"
>
<label>Strategy</label>
<input
type="text"
id="crm-edit-strategy"
placeholder="Strategy"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 120px"
>
<label>Category</label>
<input
type="text"
id="crm-edit-category"
placeholder="Category"
/>
</div>
</div>
<div class="form-row" style="flex-wrap: wrap">
<div
class="form-group"
style="flex: 1; min-width: 120px"
>
<label>Affiliate</label>
<input
type="text"
id="crm-edit-affiliate"
placeholder="Affiliate"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 120px"
>
<label>Number</label>
<input
type="text"
id="crm-edit-number"
placeholder="Phone number"
/>
</div>
<div
class="form-group"
style="flex: 1; min-width: 160px"
>
<label>Date Next Contact</label>
<input type="date" id="crm-edit-date-next" />
</div>
</div>
<div class="form-group" style="margin-top: 10px">
<label>History / Notes</label>
<textarea
id="crm-edit-history"
rows="4"
placeholder="Contact history, notes…"
style="width: 100%; resize: vertical"
></textarea>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-ghost" onclick="crmCloseEdit()">
Cancel
</button>
<button
class="btn btn-primary"
id="crm-save-btn"
onclick="crmSaveEdit()"
>
<svg
width="13"
height="13"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<polyline points="20 6 9 17 4 12" />
</svg>
Save Changes
</button>
</div>
</div>
</div>
<!-- ═══ CONFIRM DIALOG ══════════════════════════════════════════════ -->
<div class="modal-backdrop" id="confirm-backdrop">
<div class="modal" id="confirm-modal" style="max-width: 360px">
<div class="modal-header">
<span class="modal-title" id="confirm-title">Confirm</span>
<button
class="modal-close"
onclick="confirmClose()"
aria-label="Close"
>
&#x2715;
</button>
</div>
<div class="modal-body">
<p id="confirm-message" style="line-height: 1.6"></p>
</div>
<div class="modal-footer">
<button class="btn btn-ghost" onclick="confirmClose()">
Cancel
</button>
<button class="btn btn-danger" id="confirm-ok-btn">
Delete
</button>
</div>
</div>
</div>
<!-- ═══ LOGIN MODAL ═══════════════════════════════════════════════════ -->
<div id="login-backdrop">
<div id="login-modal">
<div class="login-logo">
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
>
<rect x="2" y="3" width="20" height="14" rx="2" />
<path d="M8 21h8M12 17v4" />
</svg>
<h2>derez.ai Admin</h2>
<p>Sign in with your derez.ai account</p>
</div>
<div id="login-error"></div>
<div class="modal-body">
<div class="form-group">
<label>Email</label>
<input
type="email"
id="login-email"
autocomplete="email"
placeholder="you@example.com"
/>
</div>
<div class="form-group">
<label>Password</label>
<input
type="password"
id="login-password"
autocomplete="current-password"
placeholder="••••••••"
/>
</div>
</div>
<div class="modal-footer">
<button
class="btn btn-primary"
style="width: 100%"
id="login-btn"
onclick="doSignIn()"
>
Sign In
</button>
</div>
</div>
</div>
<!-- ═══ TOAST CONTAINER ════════════════════════════════════════════ -->
<div id="toast-container"></div>
<script src="app.js"></script>
</body>
</html>