Diff -- /var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/TEMPLATES/tf_admin_company.html

O Operator
Diff

/var/www/vhosts/3dshawn.com/ptmatrix.3dshawn.com/TEMPLATES/tf_admin_company.html

added on local at 2026-07-11 18:33:05

Added
+231
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 9f6a44e066ea
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1<div class="crumbs"><a href="/admin_companies.cgi">All companies</a><span class="sep">/</span>$company_name</div>
2
3<div class="page-header">
4 <div>
5 <h1>$company_name</h1>
6 <p class="subtitle"><code>$company_slug</code> &middot; plan <strong>$plan_tier</strong> &middot; status <strong>$status</strong> &middot; seats <strong>$seat_count</strong>[if:$trial_ends_at] &middot; trial ends <span class="ts" data-ts="$trial_ends_epoch" data-fmt="datetime">$trial_ends_at</span>[/if]</p>
7 </div>
8 <div class="flex-end">
9 <a href="/admin_companies.cgi" class="btn btn-ghost">&larr; All companies</a>
10 </div>
11</div>
12
13[if:$has_flash]<div class="flash-msg">$flash</div>[/if]
14
15<style>
16 .au-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin-bottom: 18px; }
17 .au-stat { padding: 12px 14px; background: var(--col-bg-3, rgba(255,255,255,0.04)); border: 1px solid var(--col-border); border-radius: 9px; }
18 .au-stat .n { font-size: 22px; font-weight: 800; color: var(--col-text); font-family: var(--font-mono, monospace); line-height: 1.1; }
19 .au-stat .lb { font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--col-text-dim); margin-top: 4px; }
20 .au-av { width: 28px; height: 28px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-weight: 700; font-size: 11px; flex-shrink: 0; }
21 .au-clickable { cursor: pointer; transition: background 0.12s; }
22 .au-clickable:hover { background: rgba(255,255,255,0.04); }
23</style>
24
25<div class="card mb-3" style="padding:20px">
26 <h3 style="margin-top:0">Company stats</h3>
27 <div class="au-stat-grid">
28 <div class="au-stat"><div class="n">$users_total</div><div class="lb">Total users</div></div>
29 <div class="au-stat"><div class="n">$users_active</div><div class="lb">Active</div></div>
30 <div class="au-stat"><div class="n">$users_pending</div><div class="lb">Pending verify</div></div>
31 <div class="au-stat"><div class="n">$users_susp</div><div class="lb">Suspended</div></div>
32 <div class="au-stat"><div class="n">$proj_n</div><div class="lb">Projects</div></div>
33 <div class="au-stat"><div class="n">$task_n</div><div class="lb">Tasks</div></div>
34 <div class="au-stat"><div class="n">&#36;$earn_total_disp</div><div class="lb">Lifetime revenue</div></div>
35 <div class="au-stat"><div class="n">&#36;$earn_30_disp</div><div class="lb">Revenue (30d)</div></div>
36 </div>
37</div>
38
39<div class="card mb-3" style="padding:0">
40 <div class="card-header" style="padding:14px 20px"><h3 style="margin:0">Users in this company &middot; $users_total total</h3></div>
41 [if:$has_co_users]
42 <table class="table" style="margin:0">
43 <thead><tr><th>Member</th><th>Email</th><th>Role</th><th>Status</th><th>2FA</th><th>Last login</th></tr></thead>
44 <tbody>
45 [loop:@co_users]
46 <tr class="au-clickable" onclick="window.location='/admin_user.cgi?u=$loop1.id'">
47 <td><div style="display:flex;align-items:center;gap:10px"><div class="au-av" style="background:$loop1.avatar_color">$loop1.initials</div><div>$loop1.display_name_h [if:$loop1.is_super_admin]<span class="badge danger">SUPER</span>[/if]</div></div></td>
48 <td>$loop1.email_h</td>
49 <td><span class="badge">$loop1.role_label</span></td>
50 <td><span class="badge">$loop1.account_status</span></td>
51 <td>[if:$loop1.two_factor_enabled]On[/if][if:!$loop1.two_factor_enabled]Off[/if]</td>
52 <td style="font-size:12px;color:var(--col-text-dim)"><span class="ts" data-ts="$loop1.last_login_epoch" data-fmt="datetime">$loop1.last_login_disp</span></td>
53 </tr>
54 [/loop]
55 </tbody>
56 </table>
57 [/if]
58 [if:!$has_co_users]<div style="padding:18px 20px;color:var(--col-text-dim);font-size:13px">No users in this company yet.</div>[/if]
59</div>
60
61[if:$has_invoices]
62<div class="card mb-3" style="padding:0">
63 <div class="card-header" style="padding:14px 20px"><h3 style="margin:0">Recent invoices &middot; $earn_count paid lifetime</h3></div>
64 <table class="table" style="margin:0">
65 <thead><tr><th>Invoice #</th><th>Status</th><th>Paid</th><th>Due</th><th>Paid at</th><th>Created</th></tr></thead>
66 <tbody>
67 [loop:@recent_invoices]
68 <tr>
69 <td><code>$loop1.invoice_number</code></td>
70 <td><span class="badge">$loop1.status</span></td>
71 <td style="font-weight:600">$loop1.amount_disp</td>
72 <td>$loop1.due_disp</td>
73 <td style="font-size:12px;color:var(--col-text-dim)"><span class="ts" data-ts="$loop1.paid_epoch" data-fmt="datetime">$loop1.paid_at</span></td>
74 <td style="font-size:12px;color:var(--col-text-dim)"><span class="ts" data-ts="$loop1.created_epoch" data-fmt="datetime">$loop1.created_at</span></td>
75 </tr>
76 [/loop]
77 </tbody>
78 </table>
79</div>
80[/if]
81
82
83<div class="row" style="gap:18px;flex-wrap:wrap">
84 <!-- Credit balance + grant -->
85 <div class="col" style="min-width:340px;flex:1">
86 <div class="card mb-3" style="padding:20px">
87 <h3 style="margin-top:0">Account credit</h3>
88 <div class="text-muted" style="font-size:13px;margin-bottom:14px">Credits offset the customer's next invoice. Positive numbers grant credit; negative numbers adjust away credit (e.g. for reversal).</div>
89 <div style="font-size:28px;font-weight:800;margin-bottom:14px">&#36;$current_balance_disp <span class="text-muted" style="font-size:13px;font-weight:400">current balance</span></div>
90 <form method="POST" action="/admin_company.cgi">
91 <input type="hidden" name="id" value="$cid">
92 <input type="hidden" name="act" value="grant_credit">
93 <div class="row" style="gap:10px">
94 <div class="col" style="flex:0 0 140px"><div class="field"><label>Amount ($)</label><input class="input" name="amount_dollars" placeholder="25.00" required></div></div>
95 <div class="col"><div class="field"><label>Reason (shown internally)</label><input class="input" name="reason" placeholder="Goodwill credit for outage on 2026-06-12"></div></div>
96 </div>
97 <div style="display:flex;justify-content:flex-end;margin-top:12px"><button type="submit" class="btn btn-primary">Apply credit</button></div>
98 </form>
99 </div>
100
101 [if:$has_ledger]
102 <div class="card" style="padding:0">
103 <div class="card-header"><h3 style="margin:0">Credit ledger (last 20)</h3></div>
104 <table class="table" style="margin:0">
105 <thead><tr><th>When</th><th>Kind</th><th>Amount</th><th>Balance</th><th>Reason</th><th>By</th></tr></thead>
106 <tbody>
107 [loop:@ledger]
108 <tr>
109 <td style="font-size:12px"><span class="ts" data-ts="$loop1.created_epoch" data-fmt="datetime">$loop1.created_at</span></td>
110 <td><span class="badge[if:$loop1.is_credit] success[/if][if:!$loop1.is_credit] warn[/if]">$loop1.kind</span></td>
111 <td style="font-weight:600">$loop1.amount_disp</td>
112 <td>$loop1.balance_disp</td>
113 <td style="font-size:12px;color:var(--col-text-muted)">$loop1.reason</td>
114 <td style="font-size:12px;color:var(--col-text-muted)">$loop1.by_name</td>
115 </tr>
116 [/loop]
117 </tbody>
118 </table>
119 </div>
120 [/if]
121 [if:!$has_ledger]<p class="text-muted" style="padding:14px 20px;background:rgba(255,255,255,.02);border-radius:8px;font-size:13px">No credits yet.</p>[/if]
122 </div>
123
124 <!-- Tier override + locked price -->
125 <div class="col" style="min-width:340px;flex:1">
126
127 <!-- Tier override -->
128 <div class="card mb-3" style="padding:20px">
129 <h3 style="margin-top:0">Push to a higher tier free</h3>
130 <div class="text-muted" style="font-size:13px;margin-bottom:14px">Temporarily grant access to a higher plan tier without billing. Reverts automatically when the expiry date passes.</div>
131 [if:$tier_override_active]
132 <div style="padding:12px;background:rgba(34,197,94,.10);border:1px solid rgba(34,197,94,.4);border-radius:8px;margin-bottom:14px">
133 <strong style="color:#4ade80">Active:</strong> $plan_tier_override
134 [if:$tier_override_expires] &middot; expires <span class="ts" data-ts="$tier_override_expires_epoch" data-fmt="datetime">$tier_override_expires</span>[/if]
135 [if:$tier_override_reason]<div class="text-muted" style="font-size:12px;margin-top:4px">$tier_override_reason</div>[/if]
136 </div>
137 <form method="POST" action="/admin_company.cgi" style="display:inline" onsubmit="return confirm('Clear tier override?')">
138 <input type="hidden" name="id" value="$cid">
139 <input type="hidden" name="act" value="clear_tier_override">
140 <button type="submit" class="btn btn-ghost btn-sm">Clear override</button>
141 </form>
142 [/if]
143 [if:!$tier_override_active]
144 <form method="POST" action="/admin_company.cgi">
145 <input type="hidden" name="id" value="$cid">
146 <input type="hidden" name="act" value="set_tier_override">
147 <div class="row" style="gap:10px">
148 <div class="col"><div class="field"><label>Push to tier</label>
149 <select class="select" name="override_tier" required>
150 <option value="">&mdash; pick &mdash;</option>
151 <option value="starter">Starter</option>
152 <option value="pro">Pro</option>
153 <option value="business">Business</option>
154 <option value="enterprise">Enterprise</option>
155 </select>
156 </div></div>
157 <div class="col"><div class="field"><label>Expires (optional)</label><input class="input" type="date" name="expires_at"></div></div>
158 </div>
159 <div class="field" style="margin-top:10px"><label>Reason (internal)</label><input class="input" name="reason" placeholder="One-month trial extension"></div>
160 <div style="display:flex;justify-content:flex-end;margin-top:12px"><button type="submit" class="btn btn-primary">Apply override</button></div>
161 </form>
162 [/if]
163 </div>
164
165 <!-- Locked price -->
166 <div class="card" style="padding:20px">
167 <h3 style="margin-top:0">Custom price lock</h3>
168 <div class="text-muted" style="font-size:13px;margin-bottom:14px">Override the standard per-seat price for this customer. Use for negotiated rates, time-limited intro pricing, or first-100-customers grandfathered rates. Leave expiry blank to make it permanent.</div>
169 [if:$locked_price_active]
170 <div style="padding:12px;background:rgba(168,85,247,.10);border:1px solid rgba(168,85,247,.4);border-radius:8px;margin-bottom:14px">
171 <strong style="color:#c4a3f0">Active:</strong> &#36;$locked_price_disp / seat / month
172 [if:$locked_price_expires] &middot; expires <span class="ts" data-ts="$locked_price_expires_epoch" data-fmt="datetime">$locked_price_expires</span>[/if]
173 [if:$locked_price_reason]<div class="text-muted" style="font-size:12px;margin-top:4px">$locked_price_reason</div>[/if]
174 </div>
175 <form method="POST" action="/admin_company.cgi" style="display:inline" onsubmit="return confirm('Clear locked price? Customer reverts to standard tier pricing.')">
176 <input type="hidden" name="id" value="$cid">
177 <input type="hidden" name="act" value="clear_locked_price">
178 <button type="submit" class="btn btn-ghost btn-sm">Clear lock</button>
179 </form>
180 [/if]
181 [if:!$locked_price_active]
182 <form method="POST" action="/admin_company.cgi">
183 <input type="hidden" name="id" value="$cid">
184 <input type="hidden" name="act" value="set_locked_price">
185 <div class="row" style="gap:10px">
186 <div class="col"><div class="field"><label>Price ($/seat/mo)</label><input class="input" name="price_dollars" placeholder="14.99" required></div></div>
187 <div class="col"><div class="field"><label>Expires (optional, blank = permanent)</label><input class="input" type="date" name="expires_at"></div></div>
188 </div>
189 <div class="field" style="margin-top:10px"><label>Reason (internal)</label><input class="input" name="reason" placeholder="6-month intro rate, then revert to Pro standard"></div>
190 <div style="display:flex;justify-content:flex-end;margin-top:12px"><button type="submit" class="btn btn-primary">Lock price</button></div>
191 </form>
192 [/if]
193 </div>
194
195
196<div class="card mb-3" style="padding:20px">
197 <h3 style="margin-top:0">Issue refund (queued — Stripe pending)</h3>
198 <div class="text-muted" style="font-size:13px;margin-bottom:14px">Live Stripe refund is gated on activating production keys. This form queues the refund intent + applies a soft credit immediately so the customer sees relief. The worker processes queued intents once Stripe is live.</div>
199 <form method="POST" action="/admin_company.cgi">
200 <input type="hidden" name="id" value="$cid">
201 <input type="hidden" name="act" value="queue_refund">
202 <div class="row" style="gap:10px">
203 <div class="col" style="flex:0 0 200px"><div class="field"><label>Invoice ID</label><input class="input" name="invoice_id" placeholder="123" required></div></div>
204 <div class="col" style="flex:0 0 140px"><div class="field"><label>Amount ($)</label><input class="input" name="amount_dollars" placeholder="25.00" required></div></div>
205 <div class="col"><div class="field"><label>Reason (internal + on customer record)</label><input class="input" name="reason" placeholder="Customer-reported overcharge"></div></div>
206 </div>
207 <div style="display:flex;justify-content:flex-end;margin-top:12px"><button type="submit" class="btn btn-primary">Queue refund</button></div>
208 </form>
209
210 [if:$has_refunds]
211 <h4 style="margin-top:18px;font-size:13px">Recent refund intents</h4>
212 <table class="table" style="margin:0;font-size:12px">
213 <thead><tr><th>ID</th><th>Invoice</th><th>Amount</th><th>Status</th><th>Reason</th><th>When</th></tr></thead>
214 <tbody>
215 [loop:@refund_intents]
216 <tr>
217 <td><code>#$loop1.id</code></td>
218 <td><code>#$loop1.invoice_id</code></td>
219 <td>$loop1.amount_disp</td>
220 <td><span class="badge">$loop1.status</span></td>
221 <td style="color:var(--col-text-dim)">$loop1.reason</td>
222 <td style="color:var(--col-text-dim)"><span class="ts" data-ts="$loop1.requested_epoch" data-fmt="datetime">$loop1.requested_at</span></td>
223 </tr>
224 [/loop]
225 </tbody>
226 </table>
227 [/if]
228</div>
229
230</div>
231</div>