@@ -911,6 +911,33 @@ async function renderAdminUserDetail(userId) {
911911 <button class="btn ${ u . auth_restricted ? 'btn-primary' : 'btn-warning' } " id="admin-btn-toggle-auth-restriction" style="width:auto">${ u . auth_restricted ? 'Unrestrict Auth' : 'Restrict Auth' } </button>
912912 </div>
913913 </div>
914+ <div class="card">
915+ <h2 class="card-title" style="margin-bottom:16px;color:var(--accent-1)">Send Notification</h2>
916+ <p style="color:var(--text-secondary);font-size:0.88rem;margin-bottom:12px">
917+ Send a message to this user's notification inbox.
918+ </p>
919+ <form id="admin-notify-form">
920+ <div class="form-group" style="margin-bottom:12px">
921+ <label for="admin-notify-title">Title</label>
922+ <input type="text" id="admin-notify-title" placeholder="e.g. Account Update" style="width:100%" required />
923+ </div>
924+ <div class="form-group" style="margin-bottom:12px">
925+ <label for="admin-notify-message">Message</label>
926+ <textarea id="admin-notify-message" rows="3" placeholder="Write your message..." style="resize:vertical;width:100%;padding:10px 14px;background:var(--bg-input);border:1px solid var(--border);border-radius:var(--radius-sm);color:var(--text-primary);font-family:inherit;font-size:0.88rem;margin-top:6px;box-sizing:border-box" required></textarea>
927+ </div>
928+ <div class="form-group" style="margin-bottom:12px">
929+ <label for="admin-notify-type">Type</label>
930+ <select id="admin-notify-type" style="width:100%">
931+ <option value="info">Info</option>
932+ <option value="success">Success</option>
933+ <option value="warning">Warning</option>
934+ <option value="error">Error</option>
935+ </select>
936+ </div>
937+ <button type="submit" class="btn btn-primary" id="admin-btn-send-notification" style="width:auto">Send</button>
938+ <div id="admin-notify-msg" style="margin-top:8px;display:none"></div>
939+ </form>
940+ </div>
914941 </div>
915942 </div>
916943
@@ -1034,6 +1061,38 @@ function initUserActions(userId) {
10341061 }
10351062 } ) ;
10361063
1064+ $a ( '#admin-notify-form' ) ?. addEventListener ( 'submit' , async ( e ) => {
1065+ e . preventDefault ( ) ;
1066+ const btn = $a ( '#admin-btn-send-notification' ) ;
1067+ const msgEl = $a ( '#admin-notify-msg' ) ;
1068+ const titleEl = $a ( '#admin-notify-title' ) ;
1069+ const messageEl = $a ( '#admin-notify-message' ) ;
1070+ const typeEl = $a ( '#admin-notify-type' ) ;
1071+ btn . disabled = true ;
1072+ btn . innerHTML = '<span class="spinner"></span> Sending...' ;
1073+ if ( msgEl ) msgEl . style . display = 'none' ;
1074+ try {
1075+ await adminApi ( `/users/${ userId } /notify` , {
1076+ method : 'POST' ,
1077+ body : JSON . stringify ( {
1078+ title : titleEl . value . trim ( ) ,
1079+ message : messageEl . value . trim ( ) ,
1080+ type : typeEl . value ,
1081+ } ) ,
1082+ } ) ;
1083+ if ( msgEl ) { msgEl . textContent = 'Notification sent successfully' ; msgEl . style . display = 'block' ; msgEl . style . color = 'var(--accent-green)' ; }
1084+ titleEl . value = '' ;
1085+ messageEl . value = '' ;
1086+ typeEl . value = 'info' ;
1087+ btn . disabled = false ;
1088+ btn . innerHTML = 'Send' ;
1089+ } catch ( err ) {
1090+ if ( msgEl ) { msgEl . textContent = err . message ; msgEl . style . display = 'block' ; msgEl . style . color = 'var(--accent-red)' ; }
1091+ btn . disabled = false ;
1092+ btn . innerHTML = 'Send' ;
1093+ }
1094+ } ) ;
1095+
10371096 $a ( '#admin-btn-delete-user' ) ?. addEventListener ( 'click' , async ( ) => {
10381097 if ( ! confirm ( 'Are you sure you want to permanently delete this user? All their servers will be deleted. This action cannot be undone.' ) ) return ;
10391098 const btn = $a ( '#admin-btn-delete-user' ) ;
0 commit comments