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

O Operator
Diff

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

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

Added
+217
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to 5338e5acedf5
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1<style>
2 .au-grid {
3 display: grid;
4 grid-template-columns: 320px 1fr;
5 gap: 16px;
6 margin-top: 14px;
7 }
8 @media (max-width: 1000px) { .au-grid { grid-template-columns: 1fr; } }
9
10 .au-card {
11 background: var(--col-surface-1, var(--col-bg-2));
12 border: 1px solid var(--col-border);
13 border-radius: 12px;
14 padding: 18px;
15 }
16 .au-card-title {
17 font-size: 10px; font-weight: 700;
18 letter-spacing: 1.5px; text-transform: uppercase;
19 color: var(--col-text-dim);
20 margin-bottom: 12px;
21 }
22 .au-row { display: flex; justify-content: space-between; gap: 12px; padding: 7px 0; font-size: 13px; border-bottom: 1px solid var(--col-border); }
23 .au-row:last-child { border-bottom: none; }
24 .au-row .lbl { color: var(--col-text-dim); }
25 .au-row .val { color: var(--col-text); font-weight: 600; text-align: right; word-break: break-word; }
26 .au-row .val.mono { font-family: var(--font-mono, monospace); font-size: 12px; }
27
28 .au-pill {
29 font-size: 9px; font-weight: 700;
30 padding: 3px 8px; border-radius: 5px;
31 letter-spacing: 1px; text-transform: uppercase;
32 }
33 .au-pill.ok { background: rgba(34,197,94,0.18); color: #4ade80; }
34 .au-pill.warn { background: rgba(245,158,11,0.20); color: #fbbf24; }
35 .au-pill.danger { background: rgba(239,68,68,0.20); color: #f87171; }
36 .au-pill.is-admin { background: rgba(124,58,237,0.18); color: #a78bfa; }
37
38 .au-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
39 .au-actions form { margin: 0; }
40 .au-actions button {
41 width: 100%;
42 background: var(--col-surface-2, var(--col-bg-3));
43 border: 1px solid var(--col-border);
44 color: var(--col-text);
45 padding: 9px 12px;
46 border-radius: 8px;
47 cursor: pointer;
48 font-size: 13px;
49 font-weight: 600;
50 text-align: left;
51 transition: all 0.12s;
52 }
53 .au-actions button:hover { border-color: var(--col-primary); }
54 .au-actions .danger button { color: #fca5a5; border-color: rgba(239,68,68,0.30); }
55 .au-actions .danger button:hover { background: rgba(239,68,68,0.10); border-color: rgba(239,68,68,0.65); }
56 .au-actions .primary button { background: var(--col-primary); border-color: transparent; color: #fff; }
57
58 .au-table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12px; }
59 .au-table th { text-align: left; font-size: 10px; letter-spacing: 1.5px; text-transform: uppercase; color: var(--col-text-dim); padding: 8px 10px; font-weight: 700; border-bottom: 1px solid var(--col-border); }
60 .au-table td { padding: 9px 10px; border-bottom: 1px solid var(--col-border); color: var(--col-text); }
61 .au-table tr:last-child td { border-bottom: none; }
62 .au-table .mono { font-family: var(--font-mono, monospace); color: var(--col-text); }
63
64 .au-stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; margin-bottom: 14px; }
65 .au-stat { padding: 12px 14px; background: var(--col-surface-2, var(--col-bg-3)); border: 1px solid var(--col-border); border-radius: 9px; }
66 .au-stat .n { font-size: 22px; font-weight: 800; color: var(--col-text); font-family: var(--font-mono, monospace); line-height: 1.1; }
67 .au-stat .lb { font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--col-text-dim); margin-top: 4px; }
68</style>
69
70<div class="page-header">
71 <div>
72 <p class="subtitle" style="text-transform:uppercase;letter-spacing:1.5px;font-size:11px;font-weight:700;color:var(--col-text-dim)">Admin &middot; User detail</p>
73 <h1>$target_display_name</h1>
74 <p class="subtitle">$target_email &middot; user #$target_id</p>
75 </div>
76 <div>
77 <a href="/admin_users.cgi" class="btn btn-secondary">&larr; Back to search</a>
78 </div>
79</div>
80
81<div class="au-grid">
82
83 <!-- LEFT: account + admin actions -->
84 <div>
85 <div class="au-card">
86 <div class="au-card-title">Account</div>
87 <div class="au-row"><span class="lbl">Email</span><span class="val">$target_email</span></div>
88 <div class="au-row"><span class="lbl">Name</span><span class="val">$target_display_name</span></div>
89 [if:$target_job_title]<div class="au-row"><span class="lbl">Job title</span><span class="val">$target_job_title</span></div>[/if]
90 [if:$target_phone]<div class="au-row"><span class="lbl">Phone</span><span class="val mono">$target_phone</span></div>[/if]
91 <div class="au-row"><span class="lbl">Role</span><span class="val">
92 [if:$target_is_super_admin]<span class="au-pill is-admin">Super admin</span>[/if]
93 [if:!$target_is_super_admin]$target_role_display[/if]
94 </span></div>
95 <div class="au-row"><span class="lbl">Status</span><span class="val">
96 [if:$is_active]<span class="au-pill ok">Active</span>[/if]
97 [if:$is_suspended]<span class="au-pill warn">Suspended</span>[/if]
98 [if:$is_closed]<span class="au-pill danger">Closed</span>[/if]
99 [if:$is_pending_verification]<span class="au-pill warn">Pending verification</span>[/if]
100 </span></div>
101 <div class="au-row"><span class="lbl">Email verified</span><span class="val">$target_email_verified</span></div>
102 <div class="au-row"><span class="lbl">2FA</span><span class="val">$target_2fa</span></div>
103 <div class="au-row"><span class="lbl">Timezone</span><span class="val">$target_timezone</span></div>
104 <div class="au-row"><span class="lbl">Locale</span><span class="val">$target_locale</span></div>
105 <div class="au-row"><span class="lbl">Joined</span><span class="val mono"><span class="ts" data-ts="$target_created_epoch" data-fmt="datetime">$target_created_at</span></span></div>
106 <div class="au-row"><span class="lbl">Last login</span><span class="val mono"><span class="ts" data-ts="$target_last_login_epoch" data-fmt="datetime">$target_last_login_at</span></span></div>
107 </div>
108
109 <div class="au-card" style="margin-top:14px">
110 <div class="au-card-title">Admin actions</div>
111 <div class="au-actions">
112 [if:!$is_self]
113 <form method="POST" action="/admin_action.cgi" class="primary">
114 <input type="hidden" name="act" value="impersonate">
115 <input type="hidden" name="target_user_id" value="$target_id">
116 <button type="submit">Impersonate user</button>
117 </form>
118 [/if]
119 [if:$is_self]
120 <div style="font-size:11px;color:var(--col-text-dim);padding:8px 10px">This is your own account &mdash; nothing to impersonate.</div>
121 [/if]
122
123 [if:$is_active]
124 <form method="POST" action="/admin_action.cgi"
125 onsubmit="return confirm('Suspend this account? They will be logged out immediately and unable to sign in until reactivated.')">
126 <input type="hidden" name="act" value="suspend_user">
127 <input type="hidden" name="target_user_id" value="$target_id">
128 <button type="submit">Suspend account</button>
129 </form>
130 [/if]
131
132 [if:$is_suspended]
133 <form method="POST" action="/admin_action.cgi">
134 <input type="hidden" name="act" value="reactivate_user">
135 <input type="hidden" name="target_user_id" value="$target_id">
136 <button type="submit">Reactivate account</button>
137 </form>
138 [/if]
139
140 [if:!$is_self]
141 <form method="POST" action="/admin_action.cgi" class="danger"
142 onsubmit="return confirm('Close this account permanently? Data stays in the database but they can never sign in again.')">
143 <input type="hidden" name="act" value="close_user">
144 <input type="hidden" name="target_user_id" value="$target_id">
145 <button type="submit">Close account</button>
146 </form>
147 [/if]
148 </div>
149 </div>
150 </div>
151
152 <!-- RIGHT: workspace + projects + tasks + time -->
153 <div>
154 [if:$has_company]
155 <div class="au-card">
156 <div class="au-card-title">Workspace</div>
157 <div class="au-row"><span class="lbl">Name</span><span class="val"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:$company_color;margin-right:6px;vertical-align:middle"></span>$company_name</span></div>
158 <div class="au-row"><span class="lbl">Plan</span><span class="val">$company_plan</span></div>
159 <div class="au-row"><span class="lbl">Joined</span><span class="val mono"><span class="ts" data-ts="$company_joined_epoch" data-fmt="datetime">$company_joined</span></span></div>
160 <div class="au-row"><span class="lbl">Actions</span><span class="val"><a href="/admin_company.cgi?id=$company_id" style="color:var(--col-primary)">Open workspace &rarr;</a></span></div>
161 </div>
162 [/if]
163
164 <div class="au-card" style="margin-top:14px">
165 <div class="au-card-title">Activity stats</div>
166 <div class="au-stat-grid">
167 <div class="au-stat"><div class="n">$p_active</div><div class="lb">Active projects</div></div>
168 <div class="au-stat"><div class="n">$t_open</div><div class="lb">Open tasks</div></div>
169 <div class="au-stat"><div class="n">$t_done</div><div class="lb">Tasks completed</div></div>
170 <div class="au-stat"><div class="n">$tt_30d_hours</div><div class="lb">Hours (30d)</div></div>
171 <div class="au-stat"><div class="n">$tt_life_hours</div><div class="lb">Hours (lifetime)</div></div>
172 <div class="au-stat"><div class="n">$tt_billable_hours</div><div class="lb">Billable hours</div></div>
173 </div>
174 </div>
175
176 <div class="au-card" style="margin-top:14px">
177 <div class="au-card-title">Projects owned &middot; $p_total total</div>
178 [if:$has_projects]
179 <table class="au-table">
180 <thead><tr><th>Name</th><th>Status</th><th>Priority</th><th>Due</th></tr></thead>
181 <tbody>
182 [loop:@projects]
183 <tr>
184 <td><a href="/project.cgi?id=$loop1.id" style="color:inherit"><span style="display:inline-block;width:8px;height:8px;border-radius:50%;background:$loop1.color;margin-right:6px"></span>$loop1.name</a></td>
185 <td><span class="badge">$loop1.status</span></td>
186 <td><span class="badge">$loop1.priority</span></td>
187 <td class="mono"><span class="ts" data-ts="$loop1.target_due_epoch" data-fmt="date">$loop1.target_due_date</span></td>
188 </tr>
189 [/loop]
190 </tbody>
191 </table>
192 [/if]
193 [if:!$has_projects]<div style="color:var(--col-text-dim);font-size:13px;padding:10px 0">No projects owned by this user.</div>[/if]
194 </div>
195
196 <div class="au-card" style="margin-top:14px">
197 <div class="au-card-title">Assigned tasks &middot; $t_open open</div>
198 [if:$has_tasks]
199 <table class="au-table">
200 <thead><tr><th>Ticket</th><th>Title</th><th>Status</th><th>Priority</th><th>Due</th></tr></thead>
201 <tbody>
202 [loop:@tasks]
203 <tr>
204 <td class="mono"><a href="/task.cgi?id=$loop1.id" style="color:var(--col-primary)">$loop1.ticket</a></td>
205 <td>$loop1.title</td>
206 <td><span class="badge">$loop1.status</span></td>
207 <td><span class="badge">$loop1.priority</span></td>
208 <td class="mono"><span class="ts" data-ts="$loop1.due_epoch" data-fmt="date">$loop1.due_date</span></td>
209 </tr>
210 [/loop]
211 </tbody>
212 </table>
213 [/if]
214 [if:!$has_tasks]<div style="color:var(--col-text-dim);font-size:13px;padding:10px 0">No open tasks assigned to this user.</div>[/if]
215 </div>
216 </div>
217</div>