@@ -52,6 +52,14 @@ public class AuctionListController {
5252 @ FXML private Button deleteBtn ;
5353 @ FXML private Button placeBidBtn ;
5454 @ FXML private Button paySellerBtn ;
55+ @ FXML private TabPane mainTabs ;
56+ @ FXML private Tab manageUsersTab ;
57+ @ FXML private TableView <User > userTable ;
58+ @ FXML private TableColumn <User , String > colUserId ;
59+ @ FXML private TableColumn <User , String > colUsername ;
60+ @ FXML private TableColumn <User , String > colUserRole ;
61+ @ FXML private TableColumn <User , String > colUserBalance ;
62+ @ FXML private TableColumn <User , String > colUserBanned ;
5563 @ FXML private Label statusLabel ;
5664
5765 private AppState appState ;
@@ -62,8 +70,10 @@ public void init(AppState appState, Stage stage) {
6270 this .appState = appState ;
6371 this .stage = stage ;
6472 setupTable ();
73+ setupUserTable ();
6574 configureRoleButtons ();
6675 refreshTable ();
76+ refreshUsers ();
6777 stage .setTitle ("Auction Platform – " + appState .currentUser .getUsername ());
6878
6979 appState .auctionService .setStatusChangeCallback (() -> Platform .runLater (this ::refreshTable ));
@@ -118,12 +128,22 @@ private void configureRoleButtons() {
118128 show (editItemBtn , startBtn , endEarlyBtn , cancelBtn , deleteBtn );
119129 } else if (appState .currentUser instanceof Seller ) {
120130 show (addFundsBtn , withdrawBtn , createItemBtn , editItemBtn , deleteBtn , startBtn , placeBidBtn );
131+ mainTabs .getTabs ().remove (manageUsersTab );
121132 } else if (appState .currentUser instanceof Bidder ) {
122133 show (addFundsBtn , withdrawBtn , placeBidBtn );
134+ mainTabs .getTabs ().remove (manageUsersTab );
123135 }
124136 updatePaySellerButton ();
125137 }
126138
139+ private void setupUserTable () {
140+ colUserId .setCellValueFactory (c -> new SimpleStringProperty (c .getValue ().getId ()));
141+ colUsername .setCellValueFactory (c -> new SimpleStringProperty (c .getValue ().getUsername ()));
142+ colUserRole .setCellValueFactory (c -> new SimpleStringProperty (roleOf (c .getValue ())));
143+ colUserBalance .setCellValueFactory (c -> new SimpleStringProperty (balanceOf (c .getValue ())));
144+ colUserBanned .setCellValueFactory (c -> new SimpleStringProperty (bannedText (c .getValue ())));
145+ }
146+
127147 private void show (javafx .scene .Node ... nodes ) {
128148 for (javafx .scene .Node n : nodes ) { n .setVisible (true ); n .setManaged (true ); }
129149 }
@@ -289,6 +309,122 @@ private void refreshTable() {
289309 updatePaySellerButton ();
290310 }
291311
312+ @ FXML
313+ private void onRefreshUsers () {
314+ refreshUsers ();
315+ showStatus ("User list refreshed." , false );
316+ }
317+
318+ @ FXML
319+ private void onBanUser () {
320+ withSelectedUser (user -> {
321+ appState .restUserService .banUser (user .getId ());
322+ refreshUsers ();
323+ showStatus ("User banned." , false );
324+ });
325+ }
326+
327+ @ FXML
328+ private void onChangeUsername () {
329+ withSelectedUser (user -> {
330+ TextInputDialog dlg = new TextInputDialog (user .getUsername ());
331+ dlg .setTitle ("Change Username" );
332+ dlg .setHeaderText ("Enter a new username:" );
333+ dlg .showAndWait ().ifPresent (username -> {
334+ try {
335+ User updated = appState .restUserService .changeUsername (user .getId (), username .trim ());
336+ if (appState .currentUser .getId ().equals (updated .getId ())) {
337+ appState .currentUser = updated ;
338+ refreshUserInfo ();
339+ }
340+ refreshUsers ();
341+ showStatus ("Username updated." , false );
342+ } catch (Exception e ) {
343+ showStatus (e .getMessage (), true );
344+ }
345+ });
346+ });
347+ }
348+
349+ @ FXML
350+ private void onChangePassword () {
351+ withSelectedUser (user -> {
352+ Dialog <String > dlg = new Dialog <>();
353+ dlg .setTitle ("Change Password" );
354+ dlg .setHeaderText ("Enter a new password:" );
355+ PasswordField passwordField = new PasswordField ();
356+ passwordField .setPromptText ("New password" );
357+ dlg .getDialogPane ().setContent (passwordField );
358+ ButtonType saveBtn = new ButtonType ("Save" , ButtonBar .ButtonData .OK_DONE );
359+ dlg .getDialogPane ().getButtonTypes ().addAll (saveBtn , ButtonType .CANCEL );
360+ dlg .setResultConverter (btn -> btn == saveBtn ? passwordField .getText () : null );
361+ dlg .showAndWait ().ifPresent (password -> {
362+ try {
363+ appState .restUserService .changePassword (user .getId (), password );
364+ refreshUsers ();
365+ showStatus ("Password updated." , false );
366+ } catch (Exception e ) {
367+ showStatus (e .getMessage (), true );
368+ }
369+ });
370+ });
371+ }
372+
373+ @ FXML
374+ private void onDeleteUser () {
375+ withSelectedUser (user -> {
376+ Alert confirm = new Alert (Alert .AlertType .CONFIRMATION );
377+ confirm .setTitle ("Delete Account" );
378+ confirm .setHeaderText ("Delete account \" " + user .getUsername () + "\" ?" );
379+ confirm .setContentText ("This action cannot be undone." );
380+ confirm .showAndWait ()
381+ .filter (btn -> btn == ButtonType .OK )
382+ .ifPresent (btn -> {
383+ try {
384+ appState .restUserService .deleteUser (user .getId ());
385+ refreshUsers ();
386+ showStatus ("User deleted." , false );
387+ } catch (Exception e ) {
388+ showStatus (e .getMessage (), true );
389+ }
390+ });
391+ });
392+ }
393+
394+ private void refreshUsers () {
395+ if (!(appState .currentUser instanceof Admin ) || userTable == null ) return ;
396+ try {
397+ userTable .setItems (FXCollections .observableArrayList (appState .restUserService .findAllUsers ()));
398+ userTable .refresh ();
399+ } catch (Exception e ) {
400+ showStatus (e .getMessage (), true );
401+ }
402+ }
403+
404+ private void withSelectedUser (java .util .function .Consumer <User > action ) {
405+ User selected = userTable .getSelectionModel ().getSelectedItem ();
406+ if (selected == null ) { showStatus ("Select a user first." , true ); return ; }
407+ try { action .accept (selected ); }
408+ catch (Exception e ) { showStatus (e .getMessage (), true ); }
409+ }
410+
411+ private String roleOf (User user ) {
412+ if (user instanceof Admin ) return "ADMIN" ;
413+ if (user instanceof Seller ) return "SELLER" ;
414+ return "BIDDER" ;
415+ }
416+
417+ private String balanceOf (User user ) {
418+ if (user instanceof Bidder b ) return "$" + String .format ("%.2f" , b .getBalance ());
419+ if (user instanceof Seller s ) return "$" + String .format ("%.2f" , s .getBalance ());
420+ return "—" ;
421+ }
422+
423+ private String bannedText (User user ) {
424+ if (user instanceof BannableUser bu ) return bu .isBanned () ? "Yes" : "No" ;
425+ return "N/A" ;
426+ }
427+
292428 private void updatePaySellerButton () {
293429 if (paySellerBtn == null || appState == null || appState .currentUser == null ) return ;
294430 Item selected = itemTable .getSelectionModel ().getSelectedItem ();
0 commit comments