diff --git a/.gitignore b/.gitignore index 687c4d1d..9777fe96 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ #Ignoring Intellij workspace specific folders and files /**/.idea/workspace.xml /**/tasks.xml -/**/*.iml /**/.idea/libraries diff --git a/Workspace/client/client.iml b/Workspace/client/client.iml new file mode 100644 index 00000000..b561a70c --- /dev/null +++ b/Workspace/client/client.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace/client/src/main/java/com/pqt/client/Main.java b/Workspace/client/src/main/java/com/pqt/client/Main.java new file mode 100644 index 00000000..c7240576 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/Main.java @@ -0,0 +1,50 @@ +package com.pqt.client; + +import com.pqt.client.gui.main_frame.MainFrame; +import com.pqt.client.gui.modules.account_screen.AccountScreen; +import com.pqt.client.gui.modules.sale_screen.SaleScreen; +import com.pqt.client.gui.modules.stat_screen.StatScreen; +import com.pqt.client.gui.modules.stock_screen.StockScreen; +import com.pqt.client.gui.ressources.components.generics.others.SideBar; +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; +import com.pqt.client.gui.ressources.components.generics.toast.ToastFactory; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.sale.SaleService; +import com.pqt.client.module.stat.StatService; +import com.pqt.client.module.stock.StockService; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.stage.Stage; + +public class Main extends Application{ + + public static void main(String[] args){ + launch(args); + } + + @Override + public void start(Stage primaryStage) throws Exception { + SaleService saleService = new SaleService(); + StockService stockService = new StockService(); + AccountService accountService = new AccountService(); + StatService statService = new StatService(); + + MainFrame mainFrame = new MainFrame(accountService); + mainFrame.addModule(new SaleScreen(accountService, stockService, saleService), true); + mainFrame.addModule(new StockScreen(stockService, accountService)); + mainFrame.addModule(new StatScreen(statService)); + mainFrame.addModule(new AccountScreen(accountService)); + + + Scene scene = new Scene(mainFrame.getPane(), 800, 600); + scene.getStylesheets().clear(); + scene.getStylesheets().addAll(getClass().getResource(GUICssTool.getCssFilePath()).toExternalForm()); + + ToastFactory.init(primaryStage); + primaryStage.setTitle(GUIStringTool.getAppTitle()); + primaryStage.setScene(scene); + primaryStage.show(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java new file mode 100644 index 00000000..4ded52f6 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java @@ -0,0 +1,35 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.module.account.AccountService; +import javafx.scene.layout.Pane; + +public class MainFrame implements IFXComponent { + + private MainFrameView view; + private MainFrameController ctrl; + + public MainFrame(AccountService accountService) { + MainFrameModel model = new MainFrameModel(accountService); + ctrl = new MainFrameController(model); + model.addListener(ctrl); + + view = new MainFrameView(ctrl); + ctrl.setView(view); + ctrl.updateView(); + } + + public void addModule(IGuiModule module, boolean setActive){ + ctrl.addModule(module, setActive); + } + + public void addModule(IGuiModule module){ + ctrl.addModule(module, false); + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java new file mode 100644 index 00000000..180f7802 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java @@ -0,0 +1,94 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener; +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.event.Event; + +class MainFrameController implements IMainFrameModelListener { + + private MainFrameModel model; + private MainFrameView view; + private IValidatorComponentListener accountManagerAccountListener; + + MainFrameController(MainFrameModel model) { + this.model = model; + } + + void setView(MainFrameView view) { + this.view = view; + } + + void updateView(){ + view.feedAccountCollectionToManager(model.getAccounts()); + view.setCurrentAccount(model.getCurrentAccount()); + if(model.getCurrentAccount()!=null) + view.updateModuleButtonLock(model.getCurrentAccount().getPermissionLevel()); + else + view.updateModuleButtonLock(AccountLevel.getLowest()); + } + + void addModule(IGuiModule module, boolean activationRequired) { + boolean activate = activationRequired + && model.getCurrentAccount()!=null + && model.getCurrentAccount().getPermissionLevel().compareTo(module.getLowestRequiredAccountLevel())>=0; + this.view.addGuiModule(module.getModuleName(),module.getPane(), module.getLowestRequiredAccountLevel(), activate); + } + + IValidatorComponentListener getAccountManagerValidatorListener() { + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + if(view.isAccountCreationPossible()) + model.connectAccount(view.create()); + } + + @Override + public void onCancelEvent() { + model.disconnectCurrentAccount(); + } + }; + } + + IAccountComponentListener getAccountManagerAccountListener() { + return new IAccountComponentListener() { + @Override + public void onRefreshContentRequestEvent() { + + } + + @Override + public void onContentClickEvent(Event event, Account eventTarget) { + + } + + @Override + public void onAddContentRequestEvent() { + + } + + @Override + public void onRemoveContentRequestEvent(Account content) { + + } + + @Override + public void onDetailContentRequestEvent(Account content) { + + } + }; + } + + @Override + public void onAccountStatusChangedEvent(boolean status) { + updateView(); + } + + @Override + public void onAccountCollectionChangedEvent() { + updateView(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java new file mode 100644 index 00000000..c8cb5fc7 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java @@ -0,0 +1,65 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.account.listeners.IAccountListener; +import com.pqt.core.entities.user_account.Account; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.Collection; + +class MainFrameModel { + + private EventListenerList listenerList; + private AccountService accountService; + + MainFrameModel(AccountService accountService) { + listenerList = new EventListenerList(); + this.accountService = accountService; + this.accountService.addListener(new IAccountListener() { + @Override + public void onAccountStatusChangedEvent(boolean status) { + MainFrameModel.this.fireAccountStatusChangedEvent(status); + } + + @Override + public void onAccountListChangedEvent() { + MainFrameModel.this.fireAccountCollectionChangedEvent(); + } + }); + } + + private void fireAccountCollectionChangedEvent() { + Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(IMainFrameModelListener::onAccountCollectionChangedEvent); + } + + private void fireAccountStatusChangedEvent(boolean status) { + Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(l->l.onAccountStatusChangedEvent(status)); + } + + void connectAccount(Account account) { + accountService.setCurrentAccount(account); + accountService.logInCurrentAccount(account.getPassword()); + } + + void disconnectCurrentAccount() { + accountService.logOutCurrentAccount(); + } + + Collection getAccounts(){ + return accountService.getAllAccounts(); + } + + void addListener(IMainFrameModelListener listener){ + listenerList.add(IMainFrameModelListener.class, listener); + } + + void removeListener(IMainFrameModelListener listener){ + listenerList.remove(IMainFrameModelListener.class, listener); + } + + Account getCurrentAccount() { + return accountService.getCurrentAccount(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java new file mode 100644 index 00000000..7b951581 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java @@ -0,0 +1,142 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.ressources.components.AccountManager; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.components.generics.others.SideBar; +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.application.Platform; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.value.ObservableValue; +import javafx.geometry.Orientation; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.control.ToolBar; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; + +import java.util.Collection; + +class MainFrameView implements IFXComponent{ + + private final MainFrameController ctrl; + + private BorderPane mainPane; + private AccountManager accountManager; + private VBox buttonHolder; + private ObjectProperty currentAccountLevel; + + MainFrameView(MainFrameController ctrl) { + this.ctrl = ctrl; + currentAccountLevel = new SimpleObjectProperty<>(AccountLevel.getLowest()); + initGui(); + } + + private void initGui(){ + mainPane = new BorderPane(); + mainPane.getStyleClass().addAll("main-module-pane", "main-frame"); + + buttonHolder = new VBox(); + + SideBar sidebar = new SideBar(); + sidebar.setFillWidth(true); + SideBar.setVgrow(buttonHolder, Priority.ALWAYS); + buttonHolder.prefWidthProperty().bind(sidebar.widthProperty()); + sidebar.getChildren().add(buttonHolder); + + accountManager = new AccountManager(); + accountManager.addListener(ctrl.getAccountManagerValidatorListener()); + accountManager.addListener(ctrl.getAccountManagerAccountListener()); + accountManager.getPane().prefWidthProperty().bind(sidebar.widthProperty()); + sidebar.getChildren().add(accountManager.getPane()); + + mainPane.setLeft(sidebar); + + Button sidebarCtrl = new Button(); + if(sidebar.isExpanded()) + sidebarCtrl.setText(GUIStringTool.getSideBarCollapseButtonLabel()); + else + sidebarCtrl.setText(GUIStringTool.getSideBarExpandButtonLabel()); + sidebarCtrl.setOnMouseClicked(event -> { + if(sidebar.isExpanded()) + sidebar.collapse(); + else if(sidebar.isCollapsed()) + sidebar.expand(); + }); + sidebar.addListener(new ISideBarListener() { + @Override + public void onCollapsedFinished() { + sidebarCtrl.setText(GUIStringTool.getSideBarExpandButtonLabel()); + } + + @Override + public void onExpandFinished() { + sidebarCtrl.setText(GUIStringTool.getSideBarCollapseButtonLabel()); + } + }); + mainPane.setTop(sidebarCtrl); + } + + @Override + public Pane getPane() { + return mainPane; + } + + void addGuiModule(String moduleName, Pane moduleContent, AccountLevel requiredLevel, boolean setActive){ + Button button = new Button(moduleName); + button.getStyleClass().add("menu-button"); + + Runnable buttonActivationCode = ()->{ + buttonHolder.getChildren() + .stream() + .filter(Button.class::isInstance) + .map(Button.class::cast) + .forEach(b-> b.getStyleClass().remove("menu-button-selected")); + button.getStyleClass().add("menu-button-selected"); + Platform.runLater(()->{ + buttonHolder.getChildren().forEach(Node::applyCss); + mainPane.setCenter(moduleContent); + }); + }; + button.setOnMouseClicked(event-> { + if(event.getButton().equals(MouseButton.PRIMARY)) + buttonActivationCode.run(); + }); + button.setOnKeyTyped(event->{ + if (event.getCode().equals(KeyCode.ENTER)) + buttonActivationCode.run(); + }); + currentAccountLevel.addListener((obs, oldVal, newVal)->button.setDisable(requiredLevel.compareTo(newVal)>0)); + button.setDisable(requiredLevel.compareTo(currentAccountLevel.get())>0); + if(setActive) + buttonActivationCode.run(); + buttonHolder.getChildren().add(button); + } + + boolean isAccountCreationPossible(){ + return accountManager.isCreationPossible(); + } + + Account create(){ + return accountManager.create(); + } + + void setCurrentAccount(Account account){ + accountManager.setCurrentAccount(account); + } + + void feedAccountCollectionToManager(Collection accounts){ + accountManager.display(accounts); + } + + void updateModuleButtonLock(AccountLevel level) { + currentAccountLevel.setValue(level); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java new file mode 100644 index 00000000..5c876e26 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.main_frame.listeners; + +import java.util.EventListener; + +public interface IMainFrameModelListener extends EventListener{ + void onAccountStatusChangedEvent(boolean status); + void onAccountCollectionChangedEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/IGuiModule.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/IGuiModule.java new file mode 100644 index 00000000..e4dfa3d2 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/IGuiModule.java @@ -0,0 +1,9 @@ +package com.pqt.client.gui.modules; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.core.entities.user_account.AccountLevel; + +public interface IGuiModule extends IFXComponent{ + String getModuleName(); + AccountLevel getLowestRequiredAccountLevel(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreen.java new file mode 100644 index 00000000..ceee3d9e --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreen.java @@ -0,0 +1,36 @@ +package com.pqt.client.gui.modules.account_screen; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.module.account.AccountService; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.scene.layout.Pane; + +public class AccountScreen implements IGuiModule { + + private AccountScreenView view; + + public AccountScreen(AccountService accountService) { + AccountScreenModel model = new AccountScreenModel(accountService); + AccountScreenController ctrl = new AccountScreenController(model); + view = new AccountScreenView(ctrl); + + ctrl.setView(view); + ctrl.updateView(); + } + + @Override + public String getModuleName() { + return GUIStringTool.getAccountGuiModuleName(); + } + + @Override + public AccountLevel getLowestRequiredAccountLevel() { + return AccountLevel.WAITER; + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenController.java new file mode 100644 index 00000000..4cb8f15f --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenController.java @@ -0,0 +1,83 @@ +package com.pqt.client.gui.modules.account_screen; + +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; + +class AccountScreenController { + + private AccountScreenModel model; + private AccountScreenView view; + + AccountScreenController(AccountScreenModel model) { + this.model = model; + } + + void setView(AccountScreenView view) { + this.view = view; + } + + void updateView() { + updateViewAccountCollection(); + updateViewActionLock(); + } + + private void updateViewAccountCollection(){ + view.setAccountCollection(model.getAccountCollection()); + } + + private void updateViewActionLock() { + if (model.getCurrentAccount() != null) { + view.setAddAccountActionLocked(AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0); + view.setDetailAccountActionLocked(!view.isItemSelected() || AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0); + view.setRemoveAccountActionLocked(!view.isItemSelected() || AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0); + }else{ + view.setAddAccountActionLocked(true); + view.setDetailAccountActionLocked(true); + view.setRemoveAccountActionLocked(true); + } + } + + IValidatorComponentListener getDetailScreenValidationListener(){ + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + if(view.isDetailCreationPossible()){ + if(view.getDetailScreenInitialValue()!=null){ + model.modifyAccount(view.getDetailScreenInitialValue(), view.getDetailScreenCreatedValue()); + }else{ + model.addAccount(view.getDetailScreenCreatedValue()); + } + view.hideDetailScreen(); + } + } + + @Override + public void onCancelEvent() { + view.hideDetailScreen(); + } + }; + } + + void onAddAccountRequested() { + view.showDetailScreen(null, model.getLevels()); + } + + void onDetailAccountRequested() { + if(view.isItemSelected()) + view.showDetailScreen(view.getSelectedItem(), model.getLevels()); + } + + void onRemoveAccountRequested() { + if(view.isItemSelected()) + model.removeAccount(view.getSelectedItem()); + } + + void onRefreshAccountRequested() { + this.updateView(); + } + + void onSelectedAccountChanged(Account oldVal, Account newVal) { + updateViewActionLock(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenModel.java new file mode 100644 index 00000000..a1a129a0 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenModel.java @@ -0,0 +1,44 @@ +package com.pqt.client.gui.modules.account_screen; + +import com.pqt.client.module.account.AccountService; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; + +import java.util.Collection; +import java.util.EnumSet; + +//TODO MAJ les méthds modif, add et remove une fois que l'accountService prend en compte les modifs +class AccountScreenModel { + + private AccountService accountService; + + AccountScreenModel(AccountService accountService) { + this.accountService = accountService; + } + + void modifyAccount(Account oldVal, Account newVal) { + //accountService.submitAccountUpdate(oldVal, newVal); + } + + void addAccount(Account newVal) { + //accountService.submitAccountUpdate(null, newVal); + } + + void removeAccount(Account oldVal) { + //accountService.submitAccountUpdate(oldVal, null); + } + + Collection getAccountCollection() { + return accountService.getAllAccounts(); + } + + Account getCurrentAccount() { + return accountService.getCurrentAccount(); + } + + Collection getLevels() { + //TODO régler ça aussi + //return accountService.getAvailableLevels(); + return EnumSet.allOf(AccountLevel.class); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenView.java new file mode 100644 index 00000000..71a067fc --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/AccountScreenView.java @@ -0,0 +1,178 @@ +package com.pqt.client.gui.modules.account_screen; + +import com.pqt.client.gui.modules.account_screen.account_manager_screen.AccountManagerScreen; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.application.Platform; +import javafx.beans.property.SimpleStringProperty; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.*; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +class AccountScreenView implements IFXComponent{ + + private AccountScreenController ctrl; + private StackPane mainPane; + private BorderPane mainPaneContent; + private TableView tableView; + private AccountManagerScreen accountManagerScreen; + + private Button addAccountButton, detailAccountButton, removeAccountButton; + + + AccountScreenView(AccountScreenController ctrl) { + this.ctrl = ctrl; + initGui(); + } + + private void initGui() { + mainPane = new StackPane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + + mainPaneContent = new BorderPane(); + + tableView = new TableView<>(); + + tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + tableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal)-> ctrl.onSelectedAccountChanged(oldVal, newVal)); + TableColumn nameColumn = new TableColumn<>(GUIStringTool.getAccountNameColumnHeaderLabel()); + nameColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getUsername())); + tableView.getColumns().add(nameColumn); + + TableColumn levelColumn = new TableColumn<>(GUIStringTool.getAccountLevelColumnHeaderLabel()); + levelColumn.setCellValueFactory(param -> new SimpleStringProperty( + GUIStringTool.getAccountLevelStringRenderer().render(param.getValue().getPermissionLevel()) + )); + tableView.getColumns().add(levelColumn); + mainPaneContent.setCenter(tableView); + + HBox mainPaneTopContent = new HBox(); + mainPaneTopContent.setFillHeight(true); + + Label label = new Label(GUIStringTool.getAccountListTitleLabel()); + label.getStyleClass().add(GUICssTool.getTitleTextStyleClass()); + mainPaneTopContent.getChildren().add(label); + + HBox separator = new HBox(); + ToolBar buttonToolbar = new ToolBar(); + addAccountButton = new Button(GUIStringTool.getAddButtonLabel()); + addAccountButton.setOnMouseClicked(event->{ + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onAddAccountRequested(); + }); + buttonToolbar.getItems().add(addAccountButton); + detailAccountButton = new Button(GUIStringTool.getDetailButtonLabel()); + detailAccountButton.setOnMouseClicked(event->{ + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onDetailAccountRequested(); + }); + buttonToolbar.getItems().add(detailAccountButton); + removeAccountButton = new Button(GUIStringTool.getRemoveButtonLabel()); + removeAccountButton.setOnMouseClicked(event->{ + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onRemoveAccountRequested(); + }); + buttonToolbar.getItems().add(removeAccountButton); + Button refreshAccountButton = new Button(GUIStringTool.getRefreshButtonLabel()); + refreshAccountButton.setOnMouseClicked(event->{ + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onRefreshAccountRequested(); + }); + buttonToolbar.getItems().add(refreshAccountButton); + + mainPaneTopContent.getChildren().addAll(separator, buttonToolbar); + HBox.setHgrow(separator, Priority.ALWAYS); + + mainPaneContent.setTop(mainPaneTopContent); + mainPane.getChildren().add(mainPaneContent); + } + + boolean isItemSelected(){ + return tableView.getSelectionModel().getSelectedItem()!=null; + } + + Account getSelectedItem(){ + return tableView.getSelectionModel().getSelectedItem(); + } + + @Override + public Pane getPane() { + return mainPane; + } + + boolean isDetailCreationPossible() { + return accountManagerScreen!=null && accountManagerScreen.isCreationPossible(); + } + + Account getDetailScreenInitialValue() { + if(accountManagerScreen!=null) + return accountManagerScreen.getInitialValue(); + return null; + } + + Account getDetailScreenCreatedValue() { + if(accountManagerScreen!=null) + return accountManagerScreen.create(); + return null; + } + + boolean isDetailScreenShown(){ + return accountManagerScreen!=null; + } + + void showDetailScreen(Account initialValue, Collection availableLevels){ + if(!isDetailScreenShown()){ + Pane separator = new Pane(); + separator.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass()); + accountManagerScreen = new AccountManagerScreen(initialValue, availableLevels); + accountManagerScreen.addListener(ctrl.getDetailScreenValidationListener()); + + Platform.runLater(()->{ + mainPane.getChildren().addAll(separator, accountManagerScreen.getPane()); + }); + } + } + + void hideDetailScreen(){ + if(isDetailScreenShown()){ + List toRemove = mainPane.getChildren() + .stream() + .filter(node->!node.equals(mainPaneContent)) + .collect(Collectors.toList()); + + Platform.runLater(()->{ + mainPane.getChildren().removeAll(toRemove); + accountManagerScreen = null; + }); + + } + } + + void setAccountCollection(Collection accountCollection) { + Platform.runLater(()->{ + tableView.getItems().clear(); + if(accountCollection!=null) + tableView.getItems().addAll(accountCollection); + }); + } + + void setAddAccountActionLocked(boolean locked) { + addAccountButton.setDisable(locked); + } + + void setDetailAccountActionLocked(boolean locked) { + detailAccountButton.setDisable(locked); + } + + void setRemoveAccountActionLocked(boolean locked) { + removeAccountButton.setDisable(locked); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreen.java new file mode 100644 index 00000000..26cd33e2 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreen.java @@ -0,0 +1,56 @@ +package com.pqt.client.gui.modules.account_screen.account_manager_screen; + +import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.scene.layout.Pane; + +import java.util.Collection; + +//TODO à faire +public class AccountManagerScreen implements IFXValidatorComponent, IFXCreatorComponent{ + + private AccountManagerScreenModel model; + private AccountManagerScreenView view; + private AccountManagerScreenController ctrl; + + public AccountManagerScreen(Account initialValue, Collection availableLevels) { + model = new AccountManagerScreenModel(initialValue, availableLevels); + ctrl = new AccountManagerScreenController(model); + view = new AccountManagerScreenView(ctrl); + + ctrl.setView(view); + ctrl.updateView(); + } + + public Account getInitialValue(){ + return model.getInitialValue(); + } + + @Override + public Account create() { + return model.getCurrentValue(); + } + + @Override + public boolean isCreationPossible() { + return model.isCurrentValueValid(); + } + + @Override + public void addListener(IValidatorComponentListener l) { + ctrl.addListener(l); + } + + @Override + public void removeListener(IValidatorComponentListener l) { + ctrl.removeListener(l); + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenController.java new file mode 100644 index 00000000..e3b6e000 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenController.java @@ -0,0 +1,58 @@ +package com.pqt.client.gui.modules.account_screen.account_manager_screen; + +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.core.entities.user_account.AccountLevel; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; + +class AccountManagerScreenController { + + private EventListenerList listenerList; + private AccountManagerScreenView view; + private AccountManagerScreenModel model; + + AccountManagerScreenController(AccountManagerScreenModel model) { + listenerList = new EventListenerList(); + this.model = model; + } + + void setView(AccountManagerScreenView view) { + this.view = view; + } + + void updateView() { + view.setLevelCollection(model.getAccountLevelCollection()); + view.setData(model.getCurrentValue()); + } + + void addListener(IValidatorComponentListener l) { + listenerList.add(IValidatorComponentListener.class, l); + } + + void removeListener(IValidatorComponentListener l) { + listenerList.remove(IValidatorComponentListener.class, l); + } + + void onNameChanged(String oldVal, String newVal) { + model.changeName(newVal); + } + + void onPasswordChanged(String oldVal, String newVal) { + model.changePassword(newVal); + } + + void onLevelChanged(AccountLevel oldVal, AccountLevel newVal) { + model.changeLevel(newVal); + } + + void onValidationEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)) + .forEach(IValidatorComponentListener::onValidationEvent); + } + + void onCancelEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)) + .forEach(IValidatorComponentListener::onCancelEvent); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenModel.java new file mode 100644 index 00000000..e0dd15d0 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenModel.java @@ -0,0 +1,61 @@ +package com.pqt.client.gui.modules.account_screen.account_manager_screen; + +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +class AccountManagerScreenModel { + private Account currentValue; + private Account initialValue; + private Set levels; + + AccountManagerScreenModel(Account initialValue, Collection availableLevels) { + levels = new HashSet<>(); + if(availableLevels!=null) + levels.addAll(availableLevels); + this.initialValue = initialValue; + this.currentValue = (initialValue!=null?new Account(initialValue):getNewAccount()); + } + + Account getCurrentValue() { + return currentValue; + } + + Account getInitialValue() { + return initialValue; + } + + boolean isCurrentValueValid() { + return !currentValue.equals(initialValue) + && currentValue.getUsername()!=null + && !currentValue.getUsername().isEmpty() + && currentValue.getPermissionLevel()!=null; + } + + Collection getAccountLevelCollection(){ + return levels; + } + + void changeName(String username) { + currentValue.setUsername(username); + } + + void changePassword(String password) { + currentValue.setPassword(password); + } + + void changeLevel(AccountLevel level) { + currentValue.setPermissionLevel(level); + } + + private Account getNewAccount() { + Account account = new Account(); + account.setUsername(""); + account.setPassword(""); + account.setPermissionLevel(levels.stream().min(Enum::compareTo).orElse(AccountLevel.getLowest())); + return account; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenView.java new file mode 100644 index 00000000..3d9d6410 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/account_screen/account_manager_screen/AccountManagerScreenView.java @@ -0,0 +1,107 @@ +package com.pqt.client.gui.modules.account_screen.account_manager_screen; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.*; + +import java.util.Collection; + + +class AccountManagerScreenView implements IFXComponent{ + + private StackPane mainPane; + private AccountManagerScreenController ctrl; + + private ChoiceBox levelChoiceBox; + private TextField nameTextField; + private PasswordField passwordField; + + AccountManagerScreenView(AccountManagerScreenController ctrl) { + this.ctrl = ctrl; + initGui(); + } + + private void initGui() { + mainPane = new StackPane(); + + BorderPane mainPaneContent = new BorderPane(); + + + GridPane mainPaneCenterContent = new GridPane(); + mainPaneCenterContent.setAlignment(Pos.CENTER); + Label nameLabel = new Label(GUIStringTool.getUsernameLabel()); + nameTextField = new TextField(); + nameTextField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onNameChanged(oldVal, newVal)); + mainPaneCenterContent.add(nameLabel, 0, 0); + mainPaneCenterContent.add(nameTextField, 1,0); + + Label passwordLabel = new Label(GUIStringTool.getPasswordLabel()); + passwordField = new PasswordField(); + passwordField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onPasswordChanged(oldVal, newVal)); + mainPaneCenterContent.add(passwordLabel, 0, 1); + mainPaneCenterContent.add(passwordField, 1,1); + + Label levelLabel = new Label(GUIStringTool.getUserLevelLabel()); + levelChoiceBox = new ChoiceBox<>(); + levelChoiceBox.valueProperty().addListener((obs, oldVal, newVal)->ctrl.onLevelChanged(oldVal, newVal)); + mainPaneCenterContent.add(levelLabel, 0, 2); + mainPaneCenterContent.add(levelChoiceBox, 1,2); + + mainPaneContent.setCenter(mainPaneCenterContent); + + HBox mainPaneBottomContent = new HBox(); + mainPaneBottomContent.setFillHeight(true); + Button validationButton = new Button(GUIStringTool.getValidationButtonLabel()); + validationButton.setOnMouseClicked(event -> { + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onValidationEvent(); + }); + Button cancelButton = new Button(GUIStringTool.getCancelButtonLabel()); + cancelButton.setOnMouseClicked(event -> { + if (event.getButton().equals(MouseButton.PRIMARY)) + ctrl.onCancelEvent(); + }); + HBox separator = new HBox(); + + mainPaneBottomContent.getChildren().addAll(separator, validationButton, cancelButton); + HBox.setHgrow(separator, Priority.ALWAYS); + + mainPaneContent.setBottom(mainPaneBottomContent); + mainPane.getChildren().add(mainPaneContent); + } + + @Override + public Pane getPane() { + return mainPane; + } + + void setLevelCollection(Collection levelCollection) { + Platform.runLater(()->{ + levelChoiceBox.getItems().clear(); + levelChoiceBox.getItems().addAll(levelCollection); + }); + } + + void setData(Account data) { + Platform.runLater(()->{ + if(data!=null){ + nameTextField.setText(data.getUsername()); + passwordField.setText(data.getPassword()); + levelChoiceBox.setValue(data.getPermissionLevel()); + }else{ + nameTextField.setText(""); + passwordField.setText(""); + levelChoiceBox.setValue(levelChoiceBox.getItems() + .stream() + .min(Enum::compareTo) + .orElse(AccountLevel.getLowest())); + } + }); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreen.java new file mode 100644 index 00000000..c1e72268 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreen.java @@ -0,0 +1,39 @@ +package com.pqt.client.gui.modules.sale_screen; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.sale.SaleService; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.scene.layout.Pane; + +public class SaleScreen implements IGuiModule { + + private SaleScreenView view; + + public SaleScreen(AccountService accountService, StockService stockService, SaleService saleService) { + SaleScreenModel model = new SaleScreenModel(accountService, stockService, saleService); + SaleScreenController ctrl = new SaleScreenController(model); + view = new SaleScreenView(ctrl); + + ctrl.setView(view); + ctrl.updateView(); + } + + @Override + public Pane getPane() { + return view.getPane(); + } + + @Override + public String getModuleName() { + return GUIStringTool.getSaleGuiModuleName(); + } + + @Override + public AccountLevel getLowestRequiredAccountLevel() { + return AccountLevel.WAITER; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenController.java new file mode 100644 index 00000000..6640d324 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenController.java @@ -0,0 +1,191 @@ +package com.pqt.client.gui.modules.sale_screen; + +import com.pqt.client.gui.modules.sale_screen.listeners.ISaleScreenModelListener; +import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners.ISaleValidationScreenListener; +import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import com.pqt.core.entities.sale.SaleStatus; +import com.pqt.core.entities.sale.SaleType; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.event.Event; + +import java.util.List; + +class SaleScreenController { + + private SaleScreenModel model; + private SaleScreenView view; + + SaleScreenController(SaleScreenModel model) { + this.model = model; + this.model.addListener(new ISaleScreenModelListener() { + @Override + public void onSaleValidatedEvent() { + SaleScreenController.this.onSaleValidationSuccess(); + } + + @Override + public void onSaleNotValidatedEvent(SaleStatus status, Throwable cause) { + onSaleValidationError(status, cause); + } + + @Override + public void onStockUpdatedEvent() { + view.setProducts(model.getProductList()); + } + + @Override + public void onAccountConnectedStateUpdatedEvent() { + updateActionLock(); + } + + @Override + public void onAccountListUpdatedEvent() { + view.setAccounts(model.getAccountList()); + } + + + }); + } + + private void onSaleValidationSuccess() { + view.setSaleStatus(SaleStatus.ACCEPTED); + } + + private void onSaleValidationError(SaleStatus status, Throwable cause) { + view.setSaleStatus(status); + } + + void setView(SaleScreenView view) { + this.view = view; + } + + void onAccountSelectedAsBeneficiary(Account account){ + model.setSaleBeneficiary(account); + } + + private Sale getCurrentSale(){ + return model.getCurrentSale(); + } + + private void updateSale(){ + view.setSale(getCurrentSale()); + updateActionLock(); + } + + private void updateActionLock() { + boolean validationButtonEnabled = model.checkValidity(getCurrentSale()) + && model.isCurrentAccountConnected() + && model.getCurrentAccountLevel().compareTo(AccountLevel.WAITER)>=0; + view.setValidationButtonEnabled(validationButtonEnabled); + } + + private void updateData(){ + view.setProducts(fetchProductList()); + view.setSaleTypes(fetchSaleTypeList()); + view.setAccounts(fetchAccountList()); + } + + void updateView(){ + updateData(); + updateSale(); + } + + private List fetchProductList(){ + return model.getProductList(); + } + private List fetchAccountList(){ + return model.getAccountList(); + } + private List fetchSaleTypeList(){ + return model.getSaleTypeList(); + } + + ISaleComponentListener getSaleDisplayerListener() { + return new ISaleComponentListener() { + @Override + public void onComponentClickEvent(Event event, Product product) { + model.removeProductFromSale(product); + SaleScreenController.this.updateSale(); + } + + @Override + public void onRefreshContentRequestEvent() {} + + @Override + public void onContentClickEvent(Event event, Sale eventTarget) {} + + @Override + public void onAddContentRequestEvent() {} + + @Override + public void onRemoveContentRequestEvent(Sale content) {} + + @Override + public void onDetailContentRequestEvent(Sale content) {} + }; + } + + IStockComponentListener getStockDisplayerListener() { + return new IStockComponentListener() { + @Override + public void onRefreshContentRequestEvent() {} + + @Override + public void onContentClickEvent(Event event, Product eventTarget) { + if(eventTarget!=null) { + model.addProductToSale(eventTarget); + SaleScreenController.this.updateSale(); + } + } + + @Override + public void onAddContentRequestEvent() {} + + @Override + public void onRemoveContentRequestEvent(Product content) {} + + @Override + public void onDetailContentRequestEvent(Product content) {} + }; + } + + Account getDefaultAccount() { + return new Account(null, null, AccountLevel.getLowest()); + } + + IValidatorComponentListener getValidatorListener() { + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + if(model.commitSale()) + view.switchToSaleValidationWaitingMode(model.getTempSaleId(), model.getCurrentSale()); + } + + @Override + public void onCancelEvent() { + model.clearSale(); + SaleScreenController.this.updateView(); + } + }; + } + + void onSaleTypeSelected(SaleType saleType) { + model.setSaleType(saleType); + } + + ISaleValidationScreenListener getSaleValidationScreenListener() { + return saleValidatedSuccessfully -> { + view.switchToSaleCompositionMode(); + if(saleValidatedSuccessfully){ + model.clearSale(); + } + + updateView(); + }; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenModel.java new file mode 100644 index 00000000..4cfc6d54 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenModel.java @@ -0,0 +1,225 @@ +package com.pqt.client.gui.modules.sale_screen; + +import com.pqt.client.gui.modules.sale_screen.listeners.ISaleScreenModelListener; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.account.listeners.IAccountListener; +import com.pqt.client.module.sale.SaleBuilder; +import com.pqt.client.module.sale.SaleService; +import com.pqt.client.module.sale.listeners.ISaleListener; +import com.pqt.client.module.stock.Listeners.IStockListener; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import com.pqt.core.entities.sale.SaleStatus; +import com.pqt.core.entities.sale.SaleType; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +class SaleScreenModel { + + private EventListenerList listeners; + + private AccountService accountService; + private StockService stockService; + private SaleService saleService; + + private SaleBuilder currentSaleBuilder; + private long tempSaleId; + + SaleScreenModel(AccountService accountService, StockService stockService, SaleService saleService) { + if(accountService==null || stockService==null || saleService==null) + throw new NullPointerException("At least one of the following services is null : account, stock, sale"); + + listeners = new EventListenerList(); + this.accountService = accountService; + this.stockService = stockService; + this.saleService = saleService; + + saleService.addListener(new ISaleListener() { + @Override + public void onSaleValidationSuccess(long saleId) { + if(saleId == SaleScreenModel.this.tempSaleId){ + SaleScreenModel.this.fireSaleValidatedEvent(); + } + } + + @Override + public void onSaleValidationError(long saleId, Throwable cause) { + if(saleId == SaleScreenModel.this.tempSaleId){ + SaleScreenModel.this.fireSaleNotValidatedEvent(SaleStatus.ABORTED, cause); + } + } + + @Override + public void onSaleValidationRefused(long saleId, Throwable cause) { + if(saleId == SaleScreenModel.this.tempSaleId){ + SaleScreenModel.this.fireSaleNotValidatedEvent(SaleStatus.REFUSED, cause); + } + } + }); + stockService.addListener(new IStockListener() { + @Override + public void onGetProductListSuccessEvent() { + + } + + @Override + public void onGetProductListErrorEvent(Throwable cause) { + + } + + @Override + public void onGetProductListRefusedEvent(Throwable cause) { + + } + + @Override + public void onProductListUpdateSuccessEvent(long id) { + + } + + @Override + public void onProductListUpdateErrorEvent(long id, Throwable cause) { + + } + + @Override + public void onProductListUpdateRefusedEvent(long id, Throwable cause) { + + } + + @Override + public void onProductListChangedEvent() { + fireStockUpdatedEvent(); + } + }); + accountService.addListener(new IAccountListener() { + @Override + public void onAccountStatusChangedEvent(boolean status) { + fireAccountConnectedStatusUpdateEvent(); + } + + @Override + public void onAccountListChangedEvent() { + fireAccountListUpdatedEvent(); + } + }); + + clearSale(); + } + + private void fireSaleValidatedEvent() { + Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class)) + .forEach(ISaleScreenModelListener::onSaleValidatedEvent); + } + + private void fireSaleNotValidatedEvent(SaleStatus status, Throwable cause) { + Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class)) + .forEach(l->l.onSaleNotValidatedEvent(status, cause)); + } + + private void fireStockUpdatedEvent(){ + Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class)) + .forEach(ISaleScreenModelListener::onStockUpdatedEvent); + } + + private void fireAccountListUpdatedEvent(){ + Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class)) + .forEach(ISaleScreenModelListener::onAccountListUpdatedEvent); + } + + private void fireAccountConnectedStatusUpdateEvent() { + Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class)) + .forEach(ISaleScreenModelListener::onAccountConnectedStateUpdatedEvent); + } + + List getAccountList() { + return accountService.getAllAccounts(); + } + + List getSaleTypeList() { + return saleService.getSaleTypes(); + } + + Sale getCurrentSale() { + return currentSaleBuilder!=null?currentSaleBuilder.build():null; + } + + List getProductList() { + return stockService.getProducts().stream().filter(Product::isSellable).collect(Collectors.toList()); + } + + void clearSale() { + currentSaleBuilder = getNewSaleBuilder(); + tempSaleId = -1; + } + + private SaleBuilder getNewSaleBuilder(){ + SaleBuilder saleBuilder = saleService.getNewSaleBuilder(); + saleBuilder.orderedBy(accountService.getCurrentAccount()); + saleBuilder.saleType(SaleType.CASH); + return saleBuilder; + } + + boolean commitSale() { + if(!checkValidity(currentSaleBuilder.build())) + return false; + + tempSaleId = saleService.commitSale(currentSaleBuilder); + return tempSaleId!=-1; + } + + boolean checkValidity(Sale sale) { + return sale.getProducts().size()>0 + && sale.getOrderedBy()!=null + && sale.getType()!=null; + } + + long getTempSaleId(){ + return tempSaleId; + } + + void addProductToSale(Product product) { + if(currentSaleBuilder!=null) + currentSaleBuilder.addProduct(product); + } + + void removeProductFromSale(Product product) { + if(currentSaleBuilder!=null) + currentSaleBuilder.removeProduct(product); + } + + void setSaleType(SaleType saleType) { + if(currentSaleBuilder!=null) + currentSaleBuilder.saleType(saleType); + } + + void setSaleBeneficiary(Account saleBeneficiary) { + if(currentSaleBuilder!=null) + currentSaleBuilder.orderedFor(saleBeneficiary); + } + + void addListener(ISaleScreenModelListener listener){ + listeners.add(ISaleScreenModelListener.class, listener); + } + + void removeListener(ISaleScreenModelListener listener){ + listeners.remove(ISaleScreenModelListener.class, listener); + } + + boolean isCurrentAccountConnected() { + return accountService.isCurrentAccountLoggedIn(); + } + + AccountLevel getCurrentAccountLevel() { + if(accountService.getCurrentAccount()!=null) + return accountService.getCurrentAccount().getPermissionLevel(); + else + return AccountLevel.getLowest(); + } +} \ No newline at end of file diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenView.java new file mode 100644 index 00000000..f3595839 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/SaleScreenView.java @@ -0,0 +1,224 @@ +package com.pqt.client.gui.modules.sale_screen; + +import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.SaleValidationScreen; +import com.pqt.client.gui.ressources.components.CommandComposerSaleDisplayer; +import com.pqt.client.gui.ressources.components.SimpleValidator; +import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.gui.ressources.components.CategoryTabStockDisplayer; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import com.pqt.core.entities.sale.SaleStatus; +import com.pqt.core.entities.sale.SaleType; +import com.pqt.core.entities.user_account.Account; +import javafx.application.Platform; + +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.layout.*; + +import java.util.List; +import java.util.stream.Collectors; + +class SaleScreenView implements IFXComponent { + + private SaleScreenController ctrl; + + private SaleValidationScreen saleValidationScreen; + private StackPane mainPane; + private BorderPane mainPaneContent; + + private CategoryTabStockDisplayer stockDisplayer; + private CommandComposerSaleDisplayer saleDisplayer; + private TextField saleMakerAccountDisplayer; + private ChoiceBox saleBeneficiaryAccountDisplayer; + private ChoiceBox saleTypeDisplayer; + private TextField salePriceDisplayer; + private SimpleValidator validator; + + SaleScreenView(SaleScreenController ctrl) { + this.ctrl = ctrl; + initGui(); + } + + private void initGui() { + mainPane = new StackPane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + + mainPaneContent = new BorderPane(); + + /* + -----------------------CENTER PANE----------------------- + */ + { + mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty()); + mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty()); + + stockDisplayer = new CategoryTabStockDisplayer(); + stockDisplayer.addListener(ctrl.getStockDisplayerListener()); + + saleDisplayer = new CommandComposerSaleDisplayer(); + saleDisplayer.addListener(ctrl.getSaleDisplayerListener()); + + HBox mainContentCenterPane = new HBox(); + mainContentCenterPane.getChildren().addAll(stockDisplayer.getPane(), saleDisplayer.getPane()); + mainContentCenterPane.setFillHeight(true); + stockDisplayer.getPane().prefWidthProperty().bind(mainContentCenterPane.widthProperty().divide(2)); + saleDisplayer.getPane().prefWidthProperty().bind(mainContentCenterPane.widthProperty().divide(2)); + + mainPaneContent.setCenter(mainContentCenterPane); + } + /* + -----------------------BOTTOM PANE----------------------- + */ + { + HBox mainContentBottomPane = new HBox(); + mainContentBottomPane.setFillHeight(true); + mainContentBottomPane.setAlignment(Pos.CENTER); + // Sale secondary data configuration (author, beneficiary, payment type, etc... + { + saleMakerAccountDisplayer = new TextField(); + saleMakerAccountDisplayer.setEditable(false); + saleMakerAccountDisplayer.setPromptText(GUIStringTool.getSaleMakerTextFieldPromptText()); + + saleBeneficiaryAccountDisplayer = new ChoiceBox<>(); + saleBeneficiaryAccountDisplayer.setConverter(GUIStringTool.getAccountStringConverter()); + saleBeneficiaryAccountDisplayer.getSelectionModel() + .selectedItemProperty() + .addListener((observable, oldElem, newElem) -> ctrl.onAccountSelectedAsBeneficiary(newElem)); + + saleTypeDisplayer = new ChoiceBox<>(); + saleTypeDisplayer.setConverter(GUIStringTool.getSaleTypeStringConverter()); + saleTypeDisplayer.getSelectionModel() + .selectedItemProperty() + .addListener((observable, oldElem, newElem) -> ctrl.onSaleTypeSelected(newElem)); + + salePriceDisplayer = new TextField(); + salePriceDisplayer.setEditable(false); + salePriceDisplayer.setPromptText(GUIStringTool.getSalePriceTextFieldPromptText()); + + + GridPane mainContentBottomCenterPane = new CssEnabledGridPane(); + mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleMakerTextFieldLabel()), 0, 0); + mainContentBottomCenterPane.add(saleMakerAccountDisplayer, 1, 0); + mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleBeneficiaryTextFieldLabel()), 0, 1); + mainContentBottomCenterPane.add(saleBeneficiaryAccountDisplayer, 1, 1); + mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleTypeTextFieldLabel()), 0, 2); + mainContentBottomCenterPane.add(saleTypeDisplayer, 1, 2); + mainContentBottomCenterPane.add(new Label(GUIStringTool.getSalePriceTextFieldLabel()), 0, 3); + mainContentBottomCenterPane.add(salePriceDisplayer, 1, 3); + + mainContentBottomPane.getChildren().add(mainContentBottomCenterPane); + } + //Sale Validator + { + AnchorPane anchorPane = new AnchorPane(); + validator = new SimpleValidator(true); + validator.addListener(ctrl.getValidatorListener()); + anchorPane.getChildren().add(validator.getPane()); + AnchorPane.setRightAnchor(validator.getPane(), 0d); + AnchorPane.setBottomAnchor(validator.getPane(), 0d); + + mainContentBottomPane.getChildren().add(anchorPane); + HBox.setHgrow(anchorPane, Priority.ALWAYS); + } + mainPaneContent.setBottom(mainContentBottomPane); + } + /* + ------------------------MAIN PANE------------------------ + */ + mainPane.getChildren().add(mainPaneContent); + } + + @Override + public Pane getPane() { + return mainPane; + } + + void switchToSaleValidationWaitingMode(long saleId, Sale sale){ + boolean clearChildren = mainPane.getChildren().size()>1; + + Pane greyIntermediaryPane = new Pane(); + greyIntermediaryPane.getStyleClass().clear(); + greyIntermediaryPane.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass()); + + saleValidationScreen = new SaleValidationScreen(saleId, sale); + saleValidationScreen.addListener(ctrl.getSaleValidationScreenListener()); + Platform.runLater(()->{ + if(clearChildren){ + mainPane.getChildren().clear(); + mainPane.getChildren().add(mainPaneContent); + } + + StackPane.setAlignment(saleValidationScreen.getPane(), Pos.CENTER); + mainPane.getChildren().addAll(greyIntermediaryPane, saleValidationScreen.getPane()); + }); + } + + void switchToSaleCompositionMode(){ + Node[] childrenToRemove = mainPane.getChildren() + .stream() + .filter(child->!child.equals(mainPaneContent)) + .collect(Collectors.toList()) + .toArray(new Node[]{}); + Platform.runLater(()->mainPane.getChildren().removeAll(childrenToRemove)); + } + + void setProducts(List products) { + stockDisplayer.display(products); + } + + void setSaleTypes(List saleTypes) { + Platform.runLater(()->{ + saleTypeDisplayer.getItems().clear(); + if(saleTypes!=null) + saleTypeDisplayer.getItems().addAll(saleTypes); + }); + } + + void setAccounts(List accounts) { + Platform.runLater(()->{ + saleBeneficiaryAccountDisplayer.getItems().clear(); + saleBeneficiaryAccountDisplayer.getItems().add(ctrl.getDefaultAccount()); + if(accounts!=null) + saleBeneficiaryAccountDisplayer.getItems().addAll(accounts); + }); + } + + void setSale(Sale sale) { + if(sale!=null) { + saleDisplayer.display(sale); + + String price = GUIStringTool.getPriceRenderer().render(sale.getTotalPrice()); + String currentAccount = GUIStringTool.getAccountStringConverter().toString(sale.getOrderedBy()); + + Platform.runLater(() -> { + salePriceDisplayer.setText(price); + saleMakerAccountDisplayer.setText(currentAccount); + + selectElement(saleTypeDisplayer, sale.getType()); + selectElement(saleBeneficiaryAccountDisplayer, sale.getOrderedFor()); + }); + } + } + + private void selectElement(ChoiceBox choiceBox, T element){ + if(element!=null){ + if(!choiceBox.getItems().contains(element)) + choiceBox.getItems().add(element); + choiceBox.getSelectionModel().select(element); + }else + choiceBox.getSelectionModel().clearSelection(); + } + + void setSaleStatus(SaleStatus status){ + this.saleValidationScreen.setSaleStatus(status); + } + + void setValidationButtonEnabled(boolean validationButtonEnabled) { + validator.setValidationButtonEnable(validationButtonEnabled); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/listeners/ISaleScreenModelListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/listeners/ISaleScreenModelListener.java new file mode 100644 index 00000000..02996c3e --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/listeners/ISaleScreenModelListener.java @@ -0,0 +1,13 @@ +package com.pqt.client.gui.modules.sale_screen.listeners; + +import com.pqt.core.entities.sale.SaleStatus; + +import java.util.EventListener; + +public interface ISaleScreenModelListener extends EventListener { + void onSaleValidatedEvent(); + void onSaleNotValidatedEvent(SaleStatus status, Throwable cause); + void onStockUpdatedEvent(); + void onAccountConnectedStateUpdatedEvent(); + void onAccountListUpdatedEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/SaleValidationScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/SaleValidationScreen.java new file mode 100644 index 00000000..93a4b7c8 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/SaleValidationScreen.java @@ -0,0 +1,97 @@ +package com.pqt.client.gui.modules.sale_screen.sale_validation_screen; + +import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners.ISaleValidationScreenListener; +import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.sale.Sale; +import com.pqt.core.entities.sale.SaleStatus; +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.ProgressIndicator; +import javafx.scene.control.TextField; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; + +public class SaleValidationScreen { + + private Pane mainPane; + + private TextField saleStatusTextField; + private SaleStatus saleStatus; + private ProgressIndicator progressIndicator; + private Button validationButton; + + private EventListenerList listeners; + + public SaleValidationScreen(long saleId, Sale sale) { + listeners = new EventListenerList(); + mainPane = new Pane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + + saleStatus = sale.getStatus(); + + BorderPane mainPaneContent = new BorderPane(); + + GridPane centerPane = new CssEnabledGridPane(); + centerPane.setAlignment(Pos.CENTER); + + Label saleIdLabel = new Label(GUIStringTool.getSaleIdLabel()); + centerPane.add(saleIdLabel, 0, 0); + + TextField saleIdTextField = new TextField(Long.toString(saleId)); + saleIdTextField.setEditable(false); + centerPane.add(saleIdTextField, 1, 0); + + Label saleStatusLabel = new Label(GUIStringTool.getSaleStatusLabel()); + centerPane.add(saleStatusLabel, 0, 1); + + saleStatusTextField = new TextField(GUIStringTool.getSaleStatusRenderer().render(saleStatus)); + saleStatusTextField.setEditable(false); + centerPane.add(saleStatusTextField, 1, 1); + + validationButton = new Button(GUIStringTool.getOkButtonLabel()); + validationButton.setDisable(saleStatus.equals(SaleStatus.PENDING)); + validationButton.setOnMouseClicked(event->fireScreenClose(saleStatus.equals(SaleStatus.ACCEPTED))); + centerPane.add(validationButton, 1,2); + + mainPaneContent.setCenter(centerPane); + + progressIndicator = new ProgressIndicator(); + mainPaneContent.setLeft(progressIndicator); + + mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty()); + mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty()); + mainPane.getChildren().add(mainPaneContent); + } + + private void fireScreenClose(boolean saleValidatedSuccessFully) { + if(!validationButton.isDisable()){ + Arrays.stream(listeners.getListeners(ISaleValidationScreenListener.class)) + .forEach(listener->listener.onScreenClose(saleValidatedSuccessFully)); + } + } + + public void addListener(ISaleValidationScreenListener listener){ + listeners.add(ISaleValidationScreenListener.class, listener); + } + + public void setSaleStatus(SaleStatus status){ + saleStatus = status; + Platform.runLater(()->{ + validationButton.setDisable(saleStatus.equals(SaleStatus.PENDING)); + saleStatusTextField.setText(GUIStringTool.getSaleStatusRenderer().render(status)); + progressIndicator.setProgress((status.equals(SaleStatus.PENDING)?ProgressIndicator.INDETERMINATE_PROGRESS:1F)); + }); + } + + public Pane getPane(){ + return mainPane; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/listeners/ISaleValidationScreenListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/listeners/ISaleValidationScreenListener.java new file mode 100644 index 00000000..e2011357 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/sale_screen/sale_validation_screen/listeners/ISaleValidationScreenListener.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners; + +import java.util.EventListener; + +public interface ISaleValidationScreenListener extends EventListener { + void onScreenClose(boolean saleValidatedSuccessfully); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreen.java new file mode 100644 index 00000000..6ef1f98b --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreen.java @@ -0,0 +1,35 @@ +package com.pqt.client.gui.modules.stat_screen; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.module.stat.StatService; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.scene.layout.Pane; + +public class StatScreen implements IGuiModule { + + private StatScreenView view; + + public StatScreen(StatService statService) { + StatScreenModel model = new StatScreenModel(statService); + StatScreenController ctrl = new StatScreenController(model); + view = new StatScreenView(); + + ctrl.setView(view); + } + + @Override + public String getModuleName() { + return GUIStringTool.getStatGuiModuleName(); + } + + @Override + public AccountLevel getLowestRequiredAccountLevel() { + return AccountLevel.STAFF; + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenController.java new file mode 100644 index 00000000..5f2510e3 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenController.java @@ -0,0 +1,22 @@ +package com.pqt.client.gui.modules.stat_screen; + +import com.pqt.client.gui.modules.stat_screen.listeners.IStatScreenModelListener; + +class StatScreenController implements IStatScreenModelListener{ + + private StatScreenModel model; + private StatScreenView view; + + StatScreenController(StatScreenModel model) { + this.model = model; + } + + void setView(StatScreenView view) { + this.view = view; + } + + @Override + public void onStatisticsChangedEvent() { + view.display(model.getStatistics()); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenModel.java new file mode 100644 index 00000000..2add8f38 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenModel.java @@ -0,0 +1,38 @@ +package com.pqt.client.gui.modules.stat_screen; + +import com.pqt.client.gui.modules.stat_screen.listeners.IStatScreenModelListener; +import com.pqt.client.module.stat.StatService; +import com.pqt.client.module.stat.listeners.IStatListener; +import com.pqt.client.module.stat.listeners.StatListenerAdapter; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.Map; + +class StatScreenModel { + private EventListenerList listenerList; + private StatService statService; + + StatScreenModel(StatService statService) { + this.statService = statService; + listenerList = new EventListenerList(); + this.statService.addListener(new StatListenerAdapter() { + @Override + public void onGetStatSuccess() { + Arrays.stream(listenerList.getListeners(IStatScreenModelListener.class)).forEach(IStatScreenModelListener::onStatisticsChangedEvent); + } + }); + } + + Map getStatistics() { + return statService.getStats(); + } + + void addListener(IStatScreenModelListener l){ + listenerList.add(IStatScreenModelListener.class, l); + } + + void removeListener(IStatScreenModelListener l){ + listenerList.remove(IStatScreenModelListener.class, l); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenView.java new file mode 100644 index 00000000..a9a79644 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/StatScreenView.java @@ -0,0 +1,52 @@ +package com.pqt.client.gui.modules.stat_screen; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.css.GUICssTool; +import javafx.application.Platform; +import javafx.scene.control.TextArea; +import javafx.scene.layout.Pane; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +class StatScreenView implements IFXComponent { + + private TextArea statTextArea; + private Pane mainPane; + + StatScreenView() { + initGui(); + } + + private void initGui() { + mainPane = new Pane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + + statTextArea = new TextArea(); + mainPane.getChildren().add(statTextArea); + statTextArea.setId("stat-screen-text-area"); + statTextArea.setWrapText(true); + statTextArea.setEditable(false); + statTextArea.prefWidthProperty().bind(mainPane.widthProperty()); + statTextArea.prefHeightProperty().bind(mainPane.heightProperty()); + } + + void display(Map statistics){ + List lines = new ArrayList<>(); + + if(statistics!=null) + lines.addAll(statistics.keySet() + .stream() + .map(key->String.format(" * %s : %s", key, statistics.get(key))) + .collect(Collectors.toList())); + + Platform.runLater(()->lines.forEach(line -> statTextArea.appendText(line+"\n"))); + } + + @Override + public Pane getPane() { + return mainPane; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/listeners/IStatScreenModelListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/listeners/IStatScreenModelListener.java new file mode 100644 index 00000000..c02c49f8 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stat_screen/listeners/IStatScreenModelListener.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.modules.stat_screen.listeners; + +import java.util.EventListener; + +public interface IStatScreenModelListener extends EventListener { + void onStatisticsChangedEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreen.java new file mode 100644 index 00000000..4deb2d97 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreen.java @@ -0,0 +1,39 @@ +package com.pqt.client.gui.modules.stock_screen; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen; +import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreenFactory; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.scene.layout.Pane; + +public class StockScreen implements IGuiModule { + + private StockScreenView view; + + public StockScreen(StockService stockService, AccountService accountService) { + StockScreenModel model = new StockScreenModel(stockService, accountService); + StockScreenController ctrl = new StockScreenController(model); + view = new StockScreenView(ctrl, new ProductManagerScreenFactory(stockService)); + + model.addListener(ctrl); + ctrl.setView(view); + ctrl.refreshView(); + } + + @Override + public String getModuleName() { + return "Stock"; + } + + @Override + public AccountLevel getLowestRequiredAccountLevel() { + return AccountLevel.WAITER; + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenController.java new file mode 100644 index 00000000..7418e94f --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenController.java @@ -0,0 +1,112 @@ +package com.pqt.client.gui.modules.stock_screen; + + +import com.pqt.client.gui.modules.stock_screen.listeners.IStockItemEventListener; +import com.pqt.client.gui.modules.stock_screen.listeners.IStockScreenModelListener; +import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.user_account.AccountLevel; + +class StockScreenController implements IStockScreenModelListener{ + + private StockScreenModel model; + private StockScreenView view; + + StockScreenController(StockScreenModel model) { + this.model = model; + } + + void setView(StockScreenView view) { + this.view = view; + } + + void onAddProductRequest() { + detailProduct(null); + } + + void onDetailProductRequest() { + if(view.getSelectedProduct()!=null) + detailProduct(view.getSelectedProduct()); + } + + private void detailProduct(Product product){ + view.switchToDetailMode(product); + } + + IValidatorComponentListener getDetailScreenValidationListener(){ + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + if(view.isDetailScreenCreationPossible()) { + if (view.hasDetailScreenInitialValue()){ + modifyProduct(view.getDetailScreenInitialValue(), view.getDetailScreenCreation()); + }else{ + addProduct(view.getDetailScreenCreation()); + } + view.switchToGeneralMode(); + } + } + + @Override + public void onCancelEvent() { + view.switchToGeneralMode(); + } + }; + } + + void onDeleteProductRequest() { + deleteProduct(view.getSelectedProduct()); + } + + private void addProduct(Product product){ + model.commitProductAddition(product); + } + + private void modifyProduct(Product oldProduct, Product newProduct){ + model.commitProductModification(oldProduct, newProduct); + } + + private void deleteProduct(Product product){ + model.commitProductDeletion(product);; + } + + void onRefreshProductsRequest() { + refreshView(); + } + + IStockItemEventListener getProductActivationListener() { + return this::detailProduct; + } + + void refreshView(){ + view.display(model.getProductCollection()); + } + + @Override + public void onStockUpdatedEvent() { + refreshView(); + } + + @Override + public void onAcccountConnectedStatusUpdatedEvent() { + updateViewActionLock(); + } + + void updateViewActionLock(){ + if(model.isAccountConnected() && model.getConnectedAccountLevel().compareTo(AccountLevel.MASTER)>=0){ + view.setAddProductActionLocked(false); + view.setEditProductActionLocked(view.getSelectedProduct()==null); + view.setRemoveProductActionLocked(view.getSelectedProduct()==null); + }else{ + view.setAddProductActionLocked(true); + view.setEditProductActionLocked(true); + view.setRemoveProductActionLocked(true); + } + } + + void onProductSelectedChange(){ + updateViewActionLock(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenModel.java new file mode 100644 index 00000000..365c0648 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenModel.java @@ -0,0 +1,88 @@ +package com.pqt.client.gui.modules.stock_screen; + +import com.pqt.client.gui.modules.stock_screen.listeners.IStockScreenModelListener; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.account.listeners.IAccountListener; +import com.pqt.client.module.stock.Listeners.StockListenerAdapter; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.user_account.AccountLevel; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.Collection; + +class StockScreenModel { + + private StockService stockService; + private AccountService accountService; + private EventListenerList listenerList; + + StockScreenModel(StockService stockService, AccountService accountService) { + listenerList = new EventListenerList(); + this.stockService = stockService; + this.stockService.addListener(new StockListenerAdapter(){ + @Override + public void onProductListChangedEvent() { + StockScreenModel.this.fireProductCollectionChanged(); + } + }); + this.accountService = accountService; + this.accountService.addListener(new IAccountListener() { + @Override + public void onAccountStatusChangedEvent(boolean status) { + StockScreenModel.this.fireConnectedStatusChanged(); + } + + @Override + public void onAccountListChangedEvent() { + + } + }); + } + + private void fireConnectedStatusChanged() { + Arrays.stream(listenerList.getListeners(IStockScreenModelListener.class)) + .forEach(IStockScreenModelListener::onAcccountConnectedStatusUpdatedEvent); + } + + private void fireProductCollectionChanged() { + Arrays.stream(listenerList.getListeners(IStockScreenModelListener.class)) + .forEach(IStockScreenModelListener::onStockUpdatedEvent); + } + + Collection getProductCollection() { + return stockService.getProducts(); + } + + void commitProductDeletion(Product product) { + stockService.commitUpdate(stockService.getNewUpdateBuilder().removeProduct(product)); + } + + void commitProductModification(Product oldProduct, Product newProduct) { + stockService.commitUpdate(stockService.getNewUpdateBuilder().modifyProduct(oldProduct, newProduct)); + } + + void commitProductAddition(Product product) { + stockService.commitUpdate(stockService.getNewUpdateBuilder().addProduct(product)); + } + + void addListener(IStockScreenModelListener l){ + listenerList.add(IStockScreenModelListener.class, l); + } + + void removeListener(IStockScreenModelListener l){ + listenerList.remove(IStockScreenModelListener.class, l); + } + + boolean isAccountConnected() { + return accountService.isCurrentAccountLoggedIn(); + } + + AccountLevel getConnectedAccountLevel() { + if(accountService.getCurrentAccount()!=null) + return accountService.getCurrentAccount().getPermissionLevel(); + else + return AccountLevel.getLowest(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenView.java new file mode 100644 index 00000000..83034d8d --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/StockScreenView.java @@ -0,0 +1,242 @@ +package com.pqt.client.gui.modules.stock_screen; + +import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen; +import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreenFactory; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.gui.ressources.strings.IObjectStringRenderer; +import com.pqt.core.entities.product.Product; +import javafx.application.Platform; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.property.SimpleDoubleProperty; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.value.ObservableValue; +import javafx.css.PseudoClass; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.input.KeyCode; +import javafx.scene.input.MouseButton; +import javafx.scene.layout.*; +import javafx.util.Callback; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +class StockScreenView implements IFXComponent { + + private StockScreenController ctrl; + private StackPane mainPane; + private BorderPane mainPaneContent; + private TableView stockTableView; + private ProductManagerScreenFactory productManagerScreenFactory; + private ProductManagerScreen currentDetailScreen; + private Button addProductButton; + private Button detailProductButton; + private Button removeProductButton; + + StockScreenView(StockScreenController ctrl, ProductManagerScreenFactory productManagerScreenFactory) { + this.ctrl = ctrl; + this.productManagerScreenFactory = productManagerScreenFactory; + initGui(); + } + + private void initGui() { + mainPane = new StackPane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + mainPaneContent = new BorderPane(); + mainPane.getChildren().add(mainPaneContent); + mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty()); + mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty()); + + addProductButton = new Button(GUIStringTool.getAddButtonLabel()); + addProductButton.setOnMouseClicked(event -> ctrl.onAddProductRequest()); + detailProductButton = new Button(GUIStringTool.getDetailButtonLabel()); + detailProductButton.setOnMouseClicked(event -> ctrl.onDetailProductRequest()); + detailProductButton.setDisable(true); + removeProductButton = new Button(GUIStringTool.getRemoveButtonLabel()); + removeProductButton.setDisable(true); + removeProductButton.setOnMouseClicked(event -> ctrl.onDeleteProductRequest()); + Button refreshProductButton = new Button(GUIStringTool.getRefreshButtonLabel()); + refreshProductButton.setOnMouseClicked(event -> ctrl.onRefreshProductsRequest()); + + ToolBar actionToolbar = new ToolBar(); + actionToolbar.getItems().addAll(addProductButton, detailProductButton, removeProductButton, refreshProductButton); + + HBox mainPaneTopContent = new HBox(); + HBox separator = new HBox(); + mainPaneTopContent.getChildren().addAll(separator, actionToolbar); + HBox.setHgrow(separator, Priority.ALWAYS); + mainPaneContent.setTop(mainPaneTopContent); + + PseudoClass outOfStockPseudoClass = PseudoClass.getPseudoClass("stock-out"); + PseudoClass lowStockPseudoClass = PseudoClass.getPseudoClass("stock-low"); + PseudoClass highStockPseudoClass = PseudoClass.getPseudoClass("stock-high"); + stockTableView = new TableView<>(); + stockTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + stockTableView.setRowFactory(tableView->{ + TableRow row = new TableRow<>(); + row.itemProperty().addListener((obs, oldVal, newVal)->{ + if(newVal!=null){ + row.pseudoClassStateChanged(outOfStockPseudoClass, newVal.getAmountRemaining()<=0); + row.pseudoClassStateChanged(lowStockPseudoClass, newVal.getAmountRemaining()>0 && newVal.getAmountRemaining()<30); + row.pseudoClassStateChanged(highStockPseudoClass, newVal.getAmountRemaining()>=30); + }else{ + row.pseudoClassStateChanged(outOfStockPseudoClass, false); + row.pseudoClassStateChanged(lowStockPseudoClass, false); + row.pseudoClassStateChanged(highStockPseudoClass, false); + } + }); + row.setOnMouseClicked(event -> { + if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2) + ctrl.getProductActivationListener().onProductActivated(row.getItem()); + }); + row.setOnKeyTyped(event -> { + if (event.getCode().equals(KeyCode.ENTER)) + ctrl.getProductActivationListener().onProductActivated(row.getItem()); + }); + return row; + }); + stockTableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + stockTableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal)->ctrl.onProductSelectedChange()); + List> columns = new ArrayList<>(); + + columns.add(createNewTableColumn(String.class, + GUIStringTool.getProductNameColumnHeader(), + param -> new SimpleStringProperty(param.getValue().getName()), + null + )); + columns.add(createNewTableColumn(String.class, + GUIStringTool.getProductCategoryColumnHeader(), + param -> new SimpleStringProperty(param.getValue().getCategory().getName()), + null + )); + columns.add(createNewTableColumn(Integer.class, + GUIStringTool.getProductAmountRemainingColumnHeader(), + param -> new SimpleIntegerProperty(param.getValue().getAmountRemaining()).asObject(), + null + )); + columns.add(createNewTableColumn(Integer.class, + GUIStringTool.getProductAmountSoldColumnHeader(), + param -> new SimpleIntegerProperty(param.getValue().getAmountSold()).asObject(), + null + )); + columns.add(createNewTableColumn(Double.class, + GUIStringTool.getProductPriceColumnHeader(), + param -> new SimpleDoubleProperty(param.getValue().getPrice()).asObject(), + GUIStringTool.getPriceRenderer() + )); + columns.add(createNewTableColumn(Boolean.class, + GUIStringTool.getProductIsSellableColumnHeader(), + param -> new SimpleBooleanProperty(param.getValue().isSellable()), + GUIStringTool.getBooleanRenderer() + )); + + stockTableView.getColumns().addAll(columns); + mainPaneContent.setCenter(stockTableView); + } + + private TableColumn createNewTableColumn(Class clazz, + String header, + Callback, ObservableValue> cellValueFactory, + IObjectStringRenderer renderer){ + TableColumn column = new TableColumn<>(); + if(header!=null) + column.setText(header); + if(cellValueFactory!=null) + column.setCellValueFactory(cellValueFactory); + if(renderer!=null) + column.setCellFactory(table -> new TableCell() { + @Override + protected void updateItem(T item, boolean empty) { + super.updateItem(item, empty); + if (item == null || empty) { + setText(null); + setStyle(""); + } else { + setText(renderer.render(item)); + } + } + } + ); + + return column; + } + + void display(Collection productCollection){ + Platform.runLater(()->{ + this.stockTableView.getItems().clear(); + this.stockTableView.getItems().addAll(productCollection); + }); + } + + @Override + public Pane getPane() { + return mainPane; + } + + Product getSelectedProduct() { + return stockTableView.getSelectionModel().getSelectedItem(); + } + + void switchToDetailMode(Product product) { + if(currentDetailScreen==null){ + currentDetailScreen = productManagerScreenFactory.create(product); + currentDetailScreen.addListener(ctrl.getDetailScreenValidationListener()); + Pane separator = new Pane(); + separator.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass()); + Platform.runLater(()->mainPane.getChildren().addAll(separator, currentDetailScreen.getPane())); + } + } + + void switchToGeneralMode() { + if(currentDetailScreen!=null){ + List toRemove = mainPane.getChildren() + .stream() + .filter(node->!node.equals(mainPaneContent)) + .collect(Collectors.toList()); + Platform.runLater(()->{ + mainPane.getChildren().removeAll(toRemove); + currentDetailScreen = null; + }); + } + } + + boolean isDetailScreenCreationPossible() { + System.out.println("test creation possible : "); + return currentDetailScreen!=null && currentDetailScreen.isCreationPossible(); + } + + boolean hasDetailScreenInitialValue() { + return currentDetailScreen!=null && currentDetailScreen.hasInitialValue(); + } + + Product getDetailScreenInitialValue() { + if(currentDetailScreen!=null) + return currentDetailScreen.getInitialValueSnapshot(); + else + return null; + } + + Product getDetailScreenCreation() { + if(currentDetailScreen!=null) + return currentDetailScreen.create(); + else + return null; + } + + void setAddProductActionLocked(boolean locked){ + addProductButton.setDisable(locked); + } + + void setRemoveProductActionLocked(boolean locked){ + removeProductButton.setDisable(locked); + } + + void setEditProductActionLocked(boolean locked){ + detailProductButton.setDisable(locked); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockItemEventListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockItemEventListener.java new file mode 100644 index 00000000..08e002eb --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockItemEventListener.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.modules.stock_screen.listeners; + +import com.pqt.core.entities.product.Product; + +public interface IStockItemEventListener { + void onProductActivated(Product product); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockScreenModelListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockScreenModelListener.java new file mode 100644 index 00000000..54604eec --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/listeners/IStockScreenModelListener.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.modules.stock_screen.listeners; + +import java.util.EventListener; + +public interface IStockScreenModelListener extends EventListener { + void onStockUpdatedEvent(); + void onAcccountConnectedStatusUpdatedEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreen.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreen.java new file mode 100644 index 00000000..d5aee803 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreen.java @@ -0,0 +1,56 @@ +package com.pqt.client.gui.modules.stock_screen.product_manager_screen; + +import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.product.Product; +import javafx.scene.layout.Pane; + +public class ProductManagerScreen implements IFXCreatorComponent, IFXValidatorComponent { + + private ProductManagerScreenView view; + private ProductManagerScreenModel model; + private ProductManagerScreenController ctrl; + + public ProductManagerScreen(Product initialData, StockService stockService){ + model = new ProductManagerScreenModel(initialData, stockService); + ctrl = new ProductManagerScreenController(model); + view = new ProductManagerScreenView(ctrl); + ctrl.setView(view); + ctrl.updateView(); + } + + @Override + public Product create() { + return model.create(); + } + + @Override + public boolean isCreationPossible() { + return model.isProductCreationPossible(); + } + + @Override + public Pane getPane() { + return view.getPane(); + } + + @Override + public void addListener(IValidatorComponentListener l) { + ctrl.addListener(l); + } + + @Override + public void removeListener(IValidatorComponentListener l) { + ctrl.removeListener(l); + } + + public boolean hasInitialValue(){ + return model.hasInitialData(); + } + + public Product getInitialValueSnapshot(){ + return new Product(model.getInitialData()); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenController.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenController.java new file mode 100644 index 00000000..b948bf82 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenController.java @@ -0,0 +1,93 @@ +package com.pqt.client.gui.modules.stock_screen.product_manager_screen; + +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.core.entities.product.Category; +import com.pqt.core.entities.product.Product; +import javafx.beans.value.ChangeListener; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; + +class ProductManagerScreenController { + + private EventListenerList listenerList; + private ProductManagerScreenModel model; + private ProductManagerScreenView view; + + ProductManagerScreenController(ProductManagerScreenModel model) { + listenerList = new EventListenerList(); + this.model = model; + } + + void setView(ProductManagerScreenView view){ + this.view = view; + } + + ChangeListener getProductComponentSelectionListener() { + return (obs, oldValue, newValue)->{ + if(newValue!=null) { + if (model.isComponent(newValue)) + model.removeComponent(newValue); + else + model.addComponent(newValue); + updateView(); + } + }; + } + + void updateView() { + view.setProduct(model.getActualProductState()); + view.setCategoryCollection(model.getCategoryCollection()); + view.setProductCollection(model.getEligibleComponentList()); + } + + IValidatorComponentListener getValidatorListener() { + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onValidationEvent); + } + + @Override + public void onCancelEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onCancelEvent); + } + }; + } + + public void addListener(IValidatorComponentListener l) { + listenerList.add(IValidatorComponentListener.class, l); + } + + public void removeListener(IValidatorComponentListener l) { + listenerList.remove(IValidatorComponentListener.class, l); + } + + boolean isProductHighlighted(Product product) { + return model.getActualProductState().getComponents().contains(product); + } + + void onNameChanged(String oldVal, String newVal) { + model.changeName(newVal); + } + + void onPriceChanged(double oldVal, double newVal) { + model.changePrice(newVal); + } + + void onCategoryChanged(Category oldVal, Category newVal) { + model.changeCategory(newVal); + } + + void onAmountRemainingChanged(int oldVal, int newVal) { + model.changeAmountRemaining(newVal); + } + + void onAmountSoldChanged(int oldVal, int newVal) { + model.changeAmountSold(newVal); + } + + void onSellableStateChanged(boolean oldVal, boolean newVal) { + model.setSellable(newVal); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenFactory.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenFactory.java new file mode 100644 index 00000000..c583115c --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenFactory.java @@ -0,0 +1,17 @@ +package com.pqt.client.gui.modules.stock_screen.product_manager_screen; + +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.product.Product; + +public final class ProductManagerScreenFactory { + + private StockService stockService; + + public ProductManagerScreenFactory(StockService stockService) { + this.stockService = stockService; + } + + public ProductManagerScreen create(Product product){ + return new ProductManagerScreen(product, stockService); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenModel.java new file mode 100644 index 00000000..962390fb --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenModel.java @@ -0,0 +1,100 @@ +package com.pqt.client.gui.modules.stock_screen.product_manager_screen; + +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.module.stock.StockService; +import com.pqt.core.entities.product.Category; +import com.pqt.core.entities.product.LightweightProduct; +import com.pqt.core.entities.product.Product; + +import java.util.*; +import java.util.stream.Collectors; + +class ProductManagerScreenModel { + + private StockService stockService; + private Product initialData; + private Product currentData; + + ProductManagerScreenModel(Product initialData, StockService stockService) { + this.stockService = stockService; + this.initialData = initialData; + if(initialData==null) + currentData = new Product(); + else + currentData = new Product(initialData); + } + + List getEligibleComponentList() { + return stockService.getProductsExcluding(currentData); + } + + Product getActualProductState(){ + return currentData; + } + + Product create() { + if(isProductCreationPossible()) + return currentData; + else + return null; + } + + boolean isProductCreationPossible() { + return (initialData!=null && !currentData.equals(initialData)) + && !currentData.getName().isEmpty() + && currentData.getCategory()!=null + && currentData.getPrice()>=0; + } + + void addComponent(Product product) { + currentData.getComponents().add(product); + } + + void removeComponent(Product product) { + currentData.getComponents().remove(product); + } + + void changeCategory(Category category){ + this.currentData.setCategory(category); + } + + void changePrice(double price){ + this.currentData.setPrice(price); + } + + void changeName(String name){ + this.currentData.setName(name); + } + + void changeAmountRemaining(int amount){ + this.currentData.setAmountRemaining(amount); + } + + void changeAmountSold(int amount){ + this.currentData.setAmountSold(amount); + } + + void setSellable(boolean sellable){ + this.currentData.setSellable(sellable); + } + + Collection getCategoryCollection() { + return stockService.getProducts() + .stream() + .map(Product::getCategory) + .distinct() + .collect(Collectors.toList()); + } + + boolean isComponent(Product product) { + return currentData.getComponents().contains(product); + } + + boolean hasInitialData(){ + return initialData!=null; + } + + Product getInitialData(){ + return initialData; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenView.java b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenView.java new file mode 100644 index 00000000..d9118917 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/modules/stock_screen/product_manager_screen/ProductManagerScreenView.java @@ -0,0 +1,212 @@ +package com.pqt.client.gui.modules.stock_screen.product_manager_screen; + +import com.pqt.client.gui.ressources.components.SimpleValidator; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane; +import com.pqt.client.gui.ressources.components.generics.javafx_override.HighlightListCell; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.product.Category; +import com.pqt.core.entities.product.Product; +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.*; +import javafx.scene.layout.*; + +import java.text.NumberFormat; +import java.text.ParseException; +import java.util.Collection; + +class ProductManagerScreenView implements IFXComponent { + + private ProductManagerScreenController ctrl; + + private int gridLines; + private StackPane mainPane; + private BorderPane mainPaneContent; + private TextField productNameTextField, + productAmountRemainingTextField, + productAmountSoldTextField, + productPriceTextField; + private ComboBox productCategoryComboBox; + private CheckBox productSellableCheckBox; + private ListView productComponentsListView; + + ProductManagerScreenView(ProductManagerScreenController ctrl) { + this.ctrl = ctrl; + initGui(); + } + + private void initGui() { + mainPane = new StackPane(); + mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass()); + + mainPaneContent = new BorderPane(); + + GridPane mainPaneCenterContent = new CssEnabledGridPane(); + mainPaneCenterContent.setAlignment(Pos.CENTER); + gridLines = 0; + NumberFormat priceFormat = NumberFormat.getNumberInstance(); + NumberFormat intFormat = NumberFormat.getIntegerInstance(); + + Label productNameLabel = new Label(GUIStringTool.getProductNameLabel()); + productNameTextField = new TextField(); + productNameTextField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onNameChanged(oldVal,newVal)); + addLineToGrid(mainPaneCenterContent, productNameLabel, productNameTextField); + + Label productCategoryLabel = new Label(GUIStringTool.getProductCategoryLabel()); + productCategoryComboBox = new ComboBox<>(); + productCategoryComboBox.setEditable(true); + productCategoryComboBox.setConverter(GUIStringTool.getCategoryStringConverter()); + productCategoryComboBox.valueProperty().addListener((obs, oldVal, newVal)->ctrl.onCategoryChanged(oldVal, newVal)); + addLineToGrid(mainPaneCenterContent, productCategoryLabel, productCategoryComboBox); + + Label productAmountRemainingLabel = new Label(GUIStringTool.getProductAmountRemainingLabel()); + productAmountRemainingTextField = getNumberOnlyTextField(intFormat); + productAmountRemainingTextField.textProperty().addListener((obs, oldVal, newVal)->{ + try{ + int oldInt = oldVal.isEmpty()?0:Integer.parseInt(oldVal); + int newInt = newVal.isEmpty()?0:Integer.parseInt(newVal); + ctrl.onAmountRemainingChanged(oldInt, newInt); + }catch(NumberFormatException e){ + e.printStackTrace(); + } + }); + addLineToGrid(mainPaneCenterContent, productAmountRemainingLabel, productAmountRemainingTextField); + + Label productAmountSoldLabel = new Label(GUIStringTool.getProductAmountSoldLabel()); + productAmountSoldTextField = getNumberOnlyTextField(intFormat); + productAmountSoldTextField.textProperty().addListener((obs, oldVal, newVal)->{ + try{ + int oldInt = oldVal.isEmpty()?0:Integer.parseInt(oldVal); + int newInt = newVal.isEmpty()?0:Integer.parseInt(newVal); + ctrl.onAmountSoldChanged(oldInt, newInt); + }catch(NumberFormatException e){ + e.printStackTrace(); + } + }); + addLineToGrid(mainPaneCenterContent, productAmountSoldLabel, productAmountSoldTextField); + + Label productSellableLabel = new Label(GUIStringTool.getProductSellableLabel()); + productSellableCheckBox = new CheckBox(); + productSellableCheckBox.selectedProperty().addListener((obs, oldVal, newVal)->ctrl.onSellableStateChanged(oldVal,newVal)); + addLineToGrid(mainPaneCenterContent, productSellableLabel, productSellableCheckBox); + + Label productPriceLabel = new Label(GUIStringTool.getProductPriceLabel()); + productPriceTextField = getNumberOnlyTextField(priceFormat); + productPriceTextField.textProperty().addListener((obs, oldVal, newVal)->{ + try{ + ctrl.onPriceChanged((oldVal.isEmpty()?-1:Double.parseDouble(oldVal)), (newVal.isEmpty()?-1:Double.parseDouble(newVal))); + }catch(NumberFormatException e){ + e.printStackTrace(); + } + }); + addLineToGrid(mainPaneCenterContent, productPriceLabel, productPriceTextField); + + mainPaneContent.setCenter(mainPaneCenterContent); + + VBox mainPaneRightContent = new VBox(); + mainPaneRightContent.setAlignment(Pos.CENTER); + Label title = new Label(GUIStringTool.getComponentListTitleLabel()); + title.setAlignment(Pos.CENTER); + title.getStyleClass().add(GUICssTool.getTitleTextStyleClass()); + productComponentsListView = new ListView<>(); + productComponentsListView.setCellFactory(listView->new HighlightListCell(){ + @Override + protected void updateItem(Product item, boolean empty) { + super.updateItem(item, empty); + if(item==null || empty){ + setText(null); + setGraphic(null); + }else{ + setText(GUIStringTool.getSimpleProductStringRenderer().render(item)); + if(ctrl.isProductHighlighted(item)){ + if(!isHightlighted()) { + setHighLight(true); + applyCss(); + } + }else { + if (isHightlighted()) { + setHighLight(false); + applyCss(); + } + } + } + } + }); + productComponentsListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + productComponentsListView.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue)->{ + this.ctrl.getProductComponentSelectionListener().changed(obs, oldValue, newValue); + if(newValue!=null) + Platform.runLater(()->productComponentsListView.getSelectionModel().clearSelection(productComponentsListView.getSelectionModel().getSelectedIndex())); + }); + + mainPaneRightContent.getChildren().addAll(title, productComponentsListView); + mainPaneContent.setRight(mainPaneRightContent); + + HBox mainPaneBottomContent = new HBox(); + HBox separator = new HBox(); + SimpleValidator validator = new SimpleValidator(); + validator.addListener(ctrl.getValidatorListener()); + mainPaneBottomContent.getChildren().addAll(separator, validator.getPane()); + HBox.setHgrow(separator, Priority.ALWAYS); + + mainPaneContent.setBottom(mainPaneBottomContent); + mainPane.getChildren().add(mainPaneContent); + } + + private void addLineToGrid(GridPane grid, Node... nodes){ + gridLines++; + int columnIndex = 0; + for(Node node : nodes){ + grid.add(node, columnIndex, gridLines); + columnIndex++; + } + } + + private TextField getNumberOnlyTextField(NumberFormat format){ + TextField textField = new TextField(); + textField.textProperty().addListener((obs, oldValue, newValue)->{ + if(!newValue.matches("^[-+]?[0-9]+[.,]?[0-9]*$")) + Platform.runLater(()->textField.setText(oldValue)); + }); + return textField; + } + + @Override + public Pane getPane() { + return mainPane; + } + + void setProduct(Product product){ + if(product!=null){ + Platform.runLater(()->{ + productNameTextField.setText(product.getName()); + productCategoryComboBox.setValue(product.getCategory()); + productAmountRemainingTextField.setText(Integer.toString(product.getAmountRemaining())); + productAmountRemainingTextField.setEditable(product.getComponents().isEmpty()); + productAmountSoldTextField.setText(Integer.toString(product.getAmountSold())); + productComponentsListView.getItems().clear(); + productComponentsListView.getItems().addAll(product.getComponents()); + productSellableCheckBox.setSelected(product.isSellable()); + productPriceTextField.setText(Double.toString(product.getPrice())); + }); + } + + } + + void setCategoryCollection(Collection categoryCollection){ + Platform.runLater(()->{ + productCategoryComboBox.getItems().clear(); + productCategoryComboBox.getItems().addAll(categoryCollection); + }); + } + + void setProductCollection(Collection productCollection){ + Platform.runLater(()->{ + productComponentsListView.getItems().clear(); + productComponentsListView.getItems().addAll(productCollection); + }); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/AccountManager.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/AccountManager.java new file mode 100644 index 00000000..a88fb26c --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/AccountManager.java @@ -0,0 +1,162 @@ +package com.pqt.client.gui.ressources.components; + +import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent; +import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.SimpleValidatorComponentFirerer; +import com.pqt.client.gui.ressources.components.specifics.account.IFXAccountsDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.account.listeners.SimpleAccountComponentFirerer; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.scene.control.Button; +import javafx.scene.control.ChoiceBox; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.VBox; + +import java.util.Collection; + +public class AccountManager implements IFXAccountsDisplayerComponent, IFXValidatorComponent, IFXCreatorComponent { + + private Pane mainPane; + + private VBox mainDisconnectedPane, mainConnectedPane; + private TextField connectedUsernameField; + private ChoiceBox disconnectedUsernameField; + private PasswordField passwordField; + + private SimpleAccountComponentFirerer accountEventFirerer; + private SimpleValidatorComponentFirerer validatorEventFirerer; + + private Account currentAccount; + + public AccountManager() { + accountEventFirerer = new SimpleAccountComponentFirerer(); + validatorEventFirerer = new SimpleValidatorComponentFirerer(); + + currentAccount = null; + + init(); + } + + private void init() { + mainPane = new Pane(); + + mainConnectedPane = new VBox(); + mainDisconnectedPane = new VBox(); + + connectedUsernameField = new TextField(); + connectedUsernameField.setEditable(false); + + Button disconnectButton = new Button(GUIStringTool.getLogoutButtonLabel()); + disconnectButton.setOnMouseClicked(event->validatorEventFirerer.fireCancelEvent()); + disconnectButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireCancelEvent();}); + + mainConnectedPane.getChildren().addAll(connectedUsernameField, disconnectButton); + + + disconnectedUsernameField = new ChoiceBox<>(); + disconnectedUsernameField.setConverter(GUIStringTool.getAccountStringConverter()); + + passwordField = new PasswordField(); + passwordField.setPromptText(GUIStringTool.getPasswordFieldPromptText()); + + Button validationButton = new Button(GUIStringTool.getLoginButtonLabel()); + validationButton.setOnMouseClicked(event-> validatorEventFirerer.fireValidationEvent()); + validationButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireValidationEvent();}); + + mainDisconnectedPane.getChildren().addAll(disconnectedUsernameField, passwordField, validationButton); + + refreshMainPane(); + display(null); + } + + @Override + public void display(Collection content) { + Platform.runLater(()->{ + if(content!=null && content.size()>0) + disconnectedUsernameField.setItems(FXCollections.observableArrayList(content)); + else{ + disconnectedUsernameField.getItems().clear(); + disconnectedUsernameField.getItems().add(new Account("null", "", AccountLevel.getLowest())); + } + }); + } + + public void setCurrentAccount(Account account){ + currentAccount = account; + Platform.runLater(()->connectedUsernameField.setText(GUIStringTool.getAccountStringConverter().toString(currentAccount))); + refreshMainPane(); + } + + private void refreshMainPane() { + if(currentAccount!=null) + Platform.runLater( + ()->{ + mainPane.getChildren().clear(); + mainPane.getChildren().add(mainConnectedPane); + } + ); + else + Platform.runLater( + ()->{ + mainPane.getChildren().clear(); + mainPane.getChildren().add(mainDisconnectedPane); + } + ); + } + + public Account getCurrentAccount() { + return currentAccount; + } + + @Override + public void addListener(IAccountComponentListener l) { + accountEventFirerer.addListener(l); + } + + @Override + public void removeListener(IAccountComponentListener l) { + accountEventFirerer.removeListener(l); + } + + @Override + public Pane getPane() { + return mainPane; + } + + @Override + public void addListener(IValidatorComponentListener l) { + validatorEventFirerer.addListener(l); + } + + @Override + public void removeListener(IValidatorComponentListener l) { + validatorEventFirerer.removeListener(l); + } + + @Override + public Account create() { + if(!isCreationPossible()) + return null; + + return new Account(disconnectedUsernameField.getValue().getUsername(), passwordField.getText(), disconnectedUsernameField.getValue().getPermissionLevel()); + } + + @Override + public boolean isCreationPossible() { + return currentAccount==null + && disconnectedUsernameField.getAccessibleText()!=null + && !disconnectedUsernameField.getAccessibleText().isEmpty() + && passwordField.getText()!=null + && !passwordField.getText().isEmpty(); + + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CategoryTabStockDisplayer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CategoryTabStockDisplayer.java new file mode 100644 index 00000000..1e95f923 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CategoryTabStockDisplayer.java @@ -0,0 +1,129 @@ +package com.pqt.client.gui.ressources.components; + +import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener; +import com.pqt.client.gui.ressources.components.specifics.products.listeners.SimpleStockComponentFirerer; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.gui.ressources.strings.IObjectStringRenderer; +import com.pqt.core.entities.product.Product; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +public class CategoryTabStockDisplayer implements IFXDisplayerComponent, IStockComponentListener> { + + private SimpleStockComponentFirerer firerer; + private BorderPane mainPane; + private TabPane tabPane; + + public CategoryTabStockDisplayer() { + init(); + firerer = new SimpleStockComponentFirerer(); + } + + @Override + public void display(Collection content) { + final ObservableList tabs = FXCollections.observableArrayList(); + if(content!=null){ + List categories = content.stream().map(product->product.getCategory().getName()).distinct().collect(Collectors.toList()); + + for(String cat : categories){ + tabs.add(createCategoryTab(cat, content.stream().filter(p->p.getCategory().getName().equals(cat)).collect(Collectors.toList()))); + } + + } + + Platform.runLater(()->{ + tabPane.getTabs().clear(); + tabPane.getTabs().addAll(tabs); + }); + } + + @Override + public void addListener(IStockComponentListener l) { + firerer.addListener(l); + } + + @Override + public void removeListener(IStockComponentListener l) { + firerer.removeListener(l); + } + + @Override + public Pane getPane() { + return mainPane; + } + + private void init(){ + mainPane = new BorderPane(); + + Label title = new Label(GUIStringTool.getCategorytabStockDisplayerTitle()); + title.setAlignment(Pos.CENTER); + title.getStyleClass().add(GUICssTool.getTitleTextStyleClass()); + + HBox topPane = new HBox(); + topPane.setFillHeight(true); + topPane.setAlignment(Pos.CENTER); + topPane.getChildren().add(title); + + mainPane.setTop(topPane); + + tabPane = new TabPane(); + mainPane.setCenter(tabPane); + } + + private Tab createCategoryTab(String categoryName, Collection products){ + Tab tab = new Tab(categoryName); + tab.closableProperty().setValue(false); + + ListView listView = new ListView<>(); + listView.setCellFactory(list->new ListCell(){ + + @Override + protected void updateItem(Product item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setText(null); + setGraphic(null); + } else { + setText(CategoryTabStockDisplayer.getProductRenderer().render(item)); + } + } + }); + + listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + listView.setEditable(false); + listView.setOnMouseClicked(event->{ + firerer.fireContentClickEvent(event, listView.getSelectionModel().getSelectedItem()); + Platform.runLater(()->listView.getSelectionModel().clearSelection(listView.getSelectionModel().getSelectedIndex())); + }); + listView.setOnKeyTyped(event -> { + if(event.getCode().equals(KeyCode.ENTER)){ + firerer.fireContentClickEvent(event, listView.getSelectionModel().getSelectedItem()); + Platform.runLater(()->listView.getSelectionModel().clearSelection(listView.getSelectionModel().getSelectedIndex())); + event.consume(); + } + }); + + listView.setItems(FXCollections.observableArrayList(products)); + + tab.setContent(listView); + return tab; + } + + private static IObjectStringRenderer getProductRenderer(){ + return GUIStringTool.getDetailledProductStringRenderer(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CommandComposerSaleDisplayer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CommandComposerSaleDisplayer.java new file mode 100644 index 00000000..21460ac3 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/CommandComposerSaleDisplayer.java @@ -0,0 +1,96 @@ +package com.pqt.client.gui.ressources.components; + +import com.pqt.client.gui.ressources.components.specifics.sale.IFXSaleDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener; +import com.pqt.client.gui.ressources.components.specifics.sale.listeners.SimpleSaleComponentFirerer; +import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import javafx.application.Platform; +import javafx.geometry.Pos; +import javafx.scene.control.*; +import javafx.scene.input.KeyCode; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; + +public class CommandComposerSaleDisplayer implements IFXSaleDisplayerComponent { + + private SimpleSaleComponentFirerer firerer; + private BorderPane mainPane; + private ListView listView; + + private Sale sale; + + public CommandComposerSaleDisplayer() { + firerer = new SimpleSaleComponentFirerer(); + init(); + } + + private void init() { + mainPane = new BorderPane(); + + Label title = new Label(GUIStringTool.getCommandComposerTitleLabel()); + title.setAlignment(Pos.CENTER); + title.getStyleClass().add(GUICssTool.getTitleTextStyleClass()); + + HBox topPane = new HBox(); + topPane.setFillHeight(true); + topPane.setAlignment(Pos.CENTER); + topPane.getChildren().add(title); + + mainPane.setTop(topPane); + + listView = new ListView<>(); + listView.setCellFactory(list->new ListCell(){ + @Override + protected void updateItem(Product item, boolean empty) { + super.updateItem(item, empty); + + if (empty || item == null) { + setText(null); + setGraphic(null); + } else { + setText(GUIStringTool.getSaleItemStringRenderer().render(item, sale.getProducts().get(item))); + } + } + }); + listView.setEditable(false); + listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + listView.setOnMouseClicked(event->firerer.fireComponentClickEvent(event, listView.getSelectionModel().getSelectedItem())); + listView.setOnKeyTyped(event -> { + if(event.getCode().equals(KeyCode.ENTER)){ + firerer.fireComponentClickEvent(event, listView.getSelectionModel().getSelectedItem()); + } + }); + mainPane.setCenter(listView); + } + + @Override + public void display(Sale content) { + if(content ==null) + return; + + this.sale = content; + Platform.runLater(()->{ + this.listView.getItems().clear(); + this.listView.getItems().addAll(this.sale.getProducts().keySet()); + }); + } + + @Override + public void addListener(ISaleComponentListener l) { + firerer.addListener(l); + } + + @Override + public void removeListener(ISaleComponentListener l) { + firerer.removeListener(l); + } + + @Override + public Pane getPane() { + return mainPane; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/SimpleValidator.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/SimpleValidator.java new file mode 100644 index 00000000..0d895aa4 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/SimpleValidator.java @@ -0,0 +1,108 @@ +package com.pqt.client.gui.ressources.components; + +import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentFirerer; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.SimpleValidatorComponentFirerer; +import javafx.application.Platform; +import javafx.scene.control.Button; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; + +public class SimpleValidator implements IFXValidatorComponent { + + private final IValidatorComponentFirerer firerer; + private Pane pane; + private boolean askConfirmation; + private Button validationButton, cancelButton; + + public SimpleValidator() { + this(false); + } + + public SimpleValidator(boolean askConfirmation) { + firerer = new SimpleValidatorComponentFirerer(); + this.askConfirmation = askConfirmation; + } + + @Override + public void addListener(IValidatorComponentListener l) { + firerer.addListener(l); + } + + @Override + public void removeListener(IValidatorComponentListener l) { + firerer.removeListener(l); + } + + @Override + public Pane getPane() { + if(pane == null) + pane = createPane(); + return pane; + } + + private Pane createPane(){ + GridPane grid = new GridPane(); + grid.getStyleClass().add("validator"); + + validationButton = new Button(GUIStringTool.getValidationButtonLabel()); + validationButton.setOnMouseClicked(event->{ + getValidationButtonProcess().process(); + }); + grid.add(validationButton, 0,0); + + cancelButton = new Button(GUIStringTool.getCancelButtonLabel()); + cancelButton.setOnMouseClicked(event->{ + getCancelButtonProcess().process(); + }); + grid.add(cancelButton, 1, 0); + + return grid; + } + + private IButtonProcess getValidationButtonProcess(){ + return ()->{ + if(validationButton.getText().equals(GUIStringTool.getValidationButtonLabel())){ + if(askConfirmation) + Platform.runLater(()->validationButton.setText(GUIStringTool.getConfirmationValidationButtonLabel())); + else + firerer.fireValidationEvent(); + }else{ + if(validationButton.getText().equals(GUIStringTool.getConfirmationValidationButtonLabel())) + firerer.fireValidationEvent(); + Platform.runLater(()->validationButton.setText(GUIStringTool.getValidationButtonLabel())); + } + }; + } + + private IButtonProcess getCancelButtonProcess(){ + return ()->{ + if(cancelButton.getText().equals(GUIStringTool.getCancelButtonLabel())){ + if(askConfirmation) + Platform.runLater(()->cancelButton.setText(GUIStringTool.getConfirmationCancelButtonLabel())); + else + firerer.fireCancelEvent(); + }else{ + Platform.runLater(()->cancelButton.setText(GUIStringTool.getCancelButtonLabel())); + firerer.fireCancelEvent(); + } + }; + + + } + + private interface IButtonProcess{ + void process(); + } + + public void setValidationButtonEnable(boolean enable){ + this.validationButton.setDisable(!enable); + } + + public void setCancelationButtonEnable(boolean enable){ + this.cancelButton.setDisable(!enable); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/IFXComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/IFXComponent.java new file mode 100644 index 00000000..d333e909 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/IFXComponent.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.ressources.components.generics; + +import javafx.scene.layout.Pane; + +public interface IFXComponent { + Pane getPane(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/creators/IFXCreatorComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/creators/IFXCreatorComponent.java new file mode 100644 index 00000000..4a79f9d1 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/creators/IFXCreatorComponent.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.ressources.components.generics.creators; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; + +public interface IFXCreatorComponent extends IFXComponent{ + T create(); + boolean isCreationPossible(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/IFXDisplayerComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/IFXDisplayerComponent.java new file mode 100644 index 00000000..6d9ea7fb --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/IFXDisplayerComponent.java @@ -0,0 +1,10 @@ +package com.pqt.client.gui.ressources.components.generics.displayers; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener; + +public interface IFXDisplayerComponent extends IFXComponent{ + void display(T content); + void addListener(U l); + void removeListener(U l); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentFirerer.java new file mode 100644 index 00000000..9824dd5f --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentFirerer.java @@ -0,0 +1,13 @@ +package com.pqt.client.gui.ressources.components.generics.displayers.listeners; + +import javafx.event.Event; + +public interface IDisplayerComponentFirerer { + void fireRefreshContentRequestEvent(); + void fireContentClickEvent(Event event, T eventTarget); + void fireAddContentRequestEvent(); + void fireRemoveContentRequestEvent(T content); + void fireDetailContentRequestEvent(T content); + void addListener(IDisplayerComponentListener l); + void removeListener(IDisplayerComponentListener l); +} \ No newline at end of file diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentListener.java new file mode 100644 index 00000000..e2c28d07 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/IDisplayerComponentListener.java @@ -0,0 +1,13 @@ +package com.pqt.client.gui.ressources.components.generics.displayers.listeners; + +import javafx.event.Event; + +import java.util.EventListener; + +public interface IDisplayerComponentListener extends EventListener { + void onRefreshContentRequestEvent(); + void onContentClickEvent(Event event, T eventTarget); + void onAddContentRequestEvent(); + void onRemoveContentRequestEvent(T content); + void onDetailContentRequestEvent(T content); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/SimpleDisplayerComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/SimpleDisplayerComponentFirerer.java new file mode 100644 index 00000000..c1909ad0 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/displayers/listeners/SimpleDisplayerComponentFirerer.java @@ -0,0 +1,58 @@ +package com.pqt.client.gui.ressources.components.generics.displayers.listeners; + +import javafx.event.Event; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; + +public class SimpleDisplayerComponentFirerer> implements IDisplayerComponentFirerer { + + protected EventListenerList listenerList; + protected Class clazz; + + public SimpleDisplayerComponentFirerer(Class clazz) { + listenerList = new EventListenerList(); + this.clazz = clazz; + } + + @Override + public void fireRefreshContentRequestEvent() { + Arrays.stream(listenerList.getListeners(clazz)).forEach(IDisplayerComponentListener::onRefreshContentRequestEvent); + } + + @Override + public void fireContentClickEvent(Event event, T eventTarget) { + Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onContentClickEvent(event, eventTarget)); + } + + @Override + public void fireAddContentRequestEvent() { + Arrays.stream(listenerList.getListeners(clazz)).forEach(IDisplayerComponentListener::onAddContentRequestEvent); + } + + @Override + public void fireRemoveContentRequestEvent(T content) { + Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onRemoveContentRequestEvent(content)); + } + + @Override + public void fireDetailContentRequestEvent(T content) { + Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onDetailContentRequestEvent(content)); + } + + @Override + public void addListener(IDisplayerComponentListener l) throws IllegalArgumentException { + if(clazz.isInstance(l)){ + listenerList.add(clazz, clazz.cast(l)); + }else{ + throw new IllegalArgumentException("Listener must implement the following interface : "+clazz.getName()); + } + } + + @Override + public void removeListener(IDisplayerComponentListener l) { + if (clazz.isInstance(l)) { + listenerList.remove(clazz, clazz.cast(l)); + } + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/CssEnabledGridPane.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/CssEnabledGridPane.java new file mode 100644 index 00000000..3ef68e26 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/CssEnabledGridPane.java @@ -0,0 +1,11 @@ +package com.pqt.client.gui.ressources.components.generics.javafx_override; + +import javafx.scene.layout.GridPane; + +public class CssEnabledGridPane extends GridPane { + + public CssEnabledGridPane() { + super(); + this.getStyleClass().add("grid-pane"); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/HighlightListCell.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/HighlightListCell.java new file mode 100644 index 00000000..985b058c --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/javafx_override/HighlightListCell.java @@ -0,0 +1,25 @@ +package com.pqt.client.gui.ressources.components.generics.javafx_override; + +import javafx.css.PseudoClass; +import javafx.scene.control.ListCell; + +public class HighlightListCell extends ListCell { + + private PseudoClass highlightPC; + private boolean highlighted; + + public HighlightListCell() { + super(); + highlighted = false; + highlightPC = PseudoClass.getPseudoClass("highlighted"); + } + + public void setHighLight(boolean highLight){ + highlighted = highLight; + this.pseudoClassStateChanged(highlightPC, highLight); + } + + public boolean isHightlighted(){ + return highlighted; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java new file mode 100644 index 00000000..d5c5351a --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java @@ -0,0 +1,119 @@ +package com.pqt.client.gui.ressources.components.generics.others; + +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; +import javafx.animation.Animation; +import javafx.animation.Transition; +import javafx.beans.value.ObservableValue; +import javafx.css.*; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.layout.VBox; +import javafx.util.Duration; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.List; + +public class SideBar extends VBox { + + private static final StyleablePropertyFactory FACTORY = new StyleablePropertyFactory<>(VBox.getClassCssMetaData()); + + private static final CssMetaData EXPANDED_WIDTH = + FACTORY.createSizeCssMetaData("-pqt-expanded-width",p->p.expandedWidth, 100, false); + + private StyleableProperty expandedWidth; + private EventListenerList listenerList; + private Animation collapseSideBar, expandSideBar; + + /** creates a sidebar containing a vertical alignment of the given nodes */ + public SideBar(Node... children) { + listenerList = new EventListenerList(); + getStyleClass().add("sidebar"); + this.setMinWidth(0); + this.expandedWidth = new SimpleStyleableDoubleProperty(EXPANDED_WIDTH, this, "expanded-width"); + this.setPrefWidth(expandedWidth.getValue().doubleValue()); + + setAlignment(Pos.CENTER); + getChildren().addAll(children); + + // create an animation to show a sidebar. + expandSideBar = new Transition() { + { + setCycleDuration(Duration.millis(250)); + } + protected void interpolate(double frac) { + SideBar.this.setVisible(true); + final double curWidth = expandedWidth.getValue().doubleValue() * frac; + setPrefWidth(curWidth); + setTranslateX(-expandedWidth.getValue().doubleValue() + curWidth); + } + }; + expandSideBar.onFinishedProperty().set(actionEvent -> + Arrays.stream(listenerList.getListeners(ISideBarListener.class)) + .forEach(ISideBarListener::onExpandFinished) + ); + + + // create an animation to hide sidebar. + collapseSideBar = new Transition() { + { + setCycleDuration(Duration.millis(250)); + } + protected void interpolate(double frac) { + final double curWidth = expandedWidth.getValue().doubleValue() * (1.0 - frac); + setPrefWidth(curWidth); + setTranslateX(-expandedWidth.getValue().doubleValue() + curWidth); + } + }; + collapseSideBar.onFinishedProperty().set(actionEvent ->{ + setVisible(false); + Arrays.stream(listenerList.getListeners(ISideBarListener.class)) + .forEach(ISideBarListener::onCollapsedFinished); + }); + collapse(); + } + + public void expand(){ + if (expandSideBar.statusProperty().get() == Animation.Status.STOPPED + && collapseSideBar.statusProperty().get() == Animation.Status.STOPPED) { + if (!isVisible()) { + expandSideBar.play(); + } + } + } + + public void collapse(){ + if (expandSideBar.statusProperty().get() == Animation.Status.STOPPED + && collapseSideBar.statusProperty().get() == Animation.Status.STOPPED) { + if (isVisible()) { + collapseSideBar.play(); + } + } + } + + public boolean isExpanded(){ + return isVisible() && expandSideBar.statusProperty().get().equals(Animation.Status.STOPPED); + } + + public boolean isCollapsed() { + return !isVisible() && collapseSideBar.statusProperty().get().equals(Animation.Status.STOPPED); + } + + public void addListener(ISideBarListener listener){ + listenerList.add(ISideBarListener.class, listener); + } + + public void removeListener(ISideBarListener listener){ + listenerList.remove(ISideBarListener.class, listener); + } + + + public static List> getClassCssMetaData() { + return FACTORY.getCssMetaData(); + } + + @Override + public List> getCssMetaData() { + return FACTORY.getCssMetaData(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java new file mode 100644 index 00000000..2a1314ff --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java @@ -0,0 +1,9 @@ +package com.pqt.client.gui.ressources.components.generics.others.listeners; + +import java.util.EventListener; + +public interface ISideBarListener extends EventListener { + + void onCollapsedFinished(); + void onExpandFinished(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/Toast.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/Toast.java new file mode 100644 index 00000000..051cc5ac --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/Toast.java @@ -0,0 +1,54 @@ +package com.pqt.client.gui.ressources.components.generics.toast; + +import com.pqt.client.gui.ressources.css.GUICssTool; +import javafx.animation.KeyFrame; +import javafx.animation.KeyValue; +import javafx.animation.Timeline; +import javafx.scene.Scene; +import javafx.scene.layout.StackPane; +import javafx.scene.paint.Color; +import javafx.scene.text.Text; +import javafx.stage.Stage; +import javafx.stage.StageStyle; +import javafx.util.Duration; + +final class Toast { + static void toast(Stage ownerStage, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay) { + Stage toastStage = new Stage(); + toastStage.initOwner(ownerStage); + toastStage.setResizable(false); + toastStage.initStyle(StageStyle.TRANSPARENT); + + Text text = new Text(toastMsg); + text.getStyleClass().add("toast-text"); + + StackPane root = new StackPane(text); + root.getStyleClass().add("toast-pane"); + root.setOpacity(0); + + Scene scene = new Scene(root); + scene.setFill(Color.TRANSPARENT); + scene.getStylesheets().addAll(Toast.class.getResource(GUICssTool.getCssFilePath()).toExternalForm()); + toastStage.setScene(scene); + toastStage.show(); + + Timeline fadeInTimeline = new Timeline(); + KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 1)); + fadeInTimeline.getKeyFrames().add(fadeInKey1); + fadeInTimeline.setOnFinished((ae) -> + new Thread(() -> { + try { + Thread.sleep(toastDelay); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + Timeline fadeOutTimeline = new Timeline(); + KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 0)); + fadeOutTimeline.getKeyFrames().add(fadeOutKey1); + fadeOutTimeline.setOnFinished((aeb) -> toastStage.close()); + fadeOutTimeline.play(); + }).start()); + fadeInTimeline.play(); + } +} \ No newline at end of file diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/ToastFactory.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/ToastFactory.java new file mode 100644 index 00000000..d174244e --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/toast/ToastFactory.java @@ -0,0 +1,46 @@ +package com.pqt.client.gui.ressources.components.generics.toast; + +import javafx.stage.Stage; + +public class ToastFactory { + + private static ToastFactory INSTANCE = null; + + private Stage stage; + private int delay, fadeInDelay, fadeOutDelay; + + private ToastFactory(Stage stage){ + this.stage = stage; + delay = 3000; + fadeInDelay = 250; + fadeOutDelay = 250; + } + + public void setToastDelay(int msDelay){ + this.delay = msDelay; + } + + public void setToastFadeInDelay(int msDelay){ + this.fadeInDelay = msDelay; + } + + public void setToastFadeOutDelay(int msDelay){ + this.fadeOutDelay = msDelay; + } + + public void toast(String message){ + Toast.toast(stage, message, delay, fadeInDelay, fadeOutDelay); + } + + public static void init(Stage stage){ + INSTANCE = new ToastFactory(stage); + } + + public static boolean isInitialized(){ + return INSTANCE!=null; + } + + public static ToastFactory getINSTANCE(){ + return INSTANCE; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/IFXValidatorComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/IFXValidatorComponent.java new file mode 100644 index 00000000..01f96276 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/IFXValidatorComponent.java @@ -0,0 +1,9 @@ +package com.pqt.client.gui.ressources.components.generics.validators; + +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; + +public interface IFXValidatorComponent extends IFXComponent{ + void addListener(IValidatorComponentListener l); + void removeListener(IValidatorComponentListener l); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentFirerer.java new file mode 100644 index 00000000..2e44be06 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentFirerer.java @@ -0,0 +1,9 @@ +package com.pqt.client.gui.ressources.components.generics.validators.listeners; + +public interface IValidatorComponentFirerer { + void addListener(IValidatorComponentListener l); + void removeListener(IValidatorComponentListener l); + + void fireValidationEvent(); + void fireCancelEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentListener.java new file mode 100644 index 00000000..c4144f91 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/IValidatorComponentListener.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.ressources.components.generics.validators.listeners; + +import java.util.EventListener; + +public interface IValidatorComponentListener extends EventListener { + void onValidationEvent(); + void onCancelEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/SimpleValidatorComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/SimpleValidatorComponentFirerer.java new file mode 100644 index 00000000..cdaa979c --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/validators/listeners/SimpleValidatorComponentFirerer.java @@ -0,0 +1,33 @@ +package com.pqt.client.gui.ressources.components.generics.validators.listeners; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; + +public class SimpleValidatorComponentFirerer implements IValidatorComponentFirerer { + + private EventListenerList listenerList; + + public SimpleValidatorComponentFirerer() { + listenerList = new EventListenerList(); + } + + @Override + public void addListener(IValidatorComponentListener l) { + listenerList.add(IValidatorComponentListener.class, l); + } + + @Override + public void removeListener(IValidatorComponentListener l) { + listenerList.remove(IValidatorComponentListener.class, l); + } + + @Override + public void fireValidationEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onValidationEvent); + } + + @Override + public void fireCancelEvent() { + Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onCancelEvent); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/IFXAccountsDisplayerComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/IFXAccountsDisplayerComponent.java new file mode 100644 index 00000000..1c459115 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/IFXAccountsDisplayerComponent.java @@ -0,0 +1,11 @@ +package com.pqt.client.gui.ressources.components.specifics.account; + +import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener; +import com.pqt.core.entities.user_account.Account; + +import java.util.Collection; + +public interface IFXAccountsDisplayerComponent extends IFXDisplayerComponent, IAccountComponentListener> { + +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/IAccountComponentListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/IAccountComponentListener.java new file mode 100644 index 00000000..9fe3ff70 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/IAccountComponentListener.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.ressources.components.specifics.account.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener; +import com.pqt.core.entities.user_account.Account; + +public interface IAccountComponentListener extends IDisplayerComponentListener{ +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/SimpleAccountComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/SimpleAccountComponentFirerer.java new file mode 100644 index 00000000..8f06f6a2 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/account/listeners/SimpleAccountComponentFirerer.java @@ -0,0 +1,10 @@ +package com.pqt.client.gui.ressources.components.specifics.account.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer; +import com.pqt.core.entities.user_account.Account; + +public class SimpleAccountComponentFirerer extends SimpleDisplayerComponentFirerer { + public SimpleAccountComponentFirerer() { + super(IAccountComponentListener.class); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/IFXProductsDisplayerComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/IFXProductsDisplayerComponent.java new file mode 100644 index 00000000..5411b73d --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/IFXProductsDisplayerComponent.java @@ -0,0 +1,10 @@ +package com.pqt.client.gui.ressources.components.specifics.products; + +import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener; +import com.pqt.core.entities.product.Product; + +import java.util.Collection; + +public interface IFXProductsDisplayerComponent extends IFXDisplayerComponent, IStockComponentListener> { +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/IStockComponentListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/IStockComponentListener.java new file mode 100644 index 00000000..0dffba47 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/IStockComponentListener.java @@ -0,0 +1,7 @@ +package com.pqt.client.gui.ressources.components.specifics.products.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener; +import com.pqt.core.entities.product.Product; + +public interface IStockComponentListener extends IDisplayerComponentListener { +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/SimpleStockComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/SimpleStockComponentFirerer.java new file mode 100644 index 00000000..5832a288 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/products/listeners/SimpleStockComponentFirerer.java @@ -0,0 +1,11 @@ +package com.pqt.client.gui.ressources.components.specifics.products.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer; +import com.pqt.core.entities.product.Product; + +public class SimpleStockComponentFirerer extends SimpleDisplayerComponentFirerer { + + public SimpleStockComponentFirerer() { + super(IStockComponentListener.class); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/IFXSaleDisplayerComponent.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/IFXSaleDisplayerComponent.java new file mode 100644 index 00000000..5f0a0fbc --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/IFXSaleDisplayerComponent.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.ressources.components.specifics.sale; + +import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent; +import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener; +import com.pqt.core.entities.sale.Sale; + +public interface IFXSaleDisplayerComponent extends IFXDisplayerComponent { +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/ISaleComponentListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/ISaleComponentListener.java new file mode 100644 index 00000000..f64fbc7f --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/ISaleComponentListener.java @@ -0,0 +1,10 @@ +package com.pqt.client.gui.ressources.components.specifics.sale.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import javafx.event.Event; + +public interface ISaleComponentListener extends IDisplayerComponentListener { + void onComponentClickEvent(Event event, Product product); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/SimpleSaleComponentFirerer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/SimpleSaleComponentFirerer.java new file mode 100644 index 00000000..aa83a903 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/specifics/sale/listeners/SimpleSaleComponentFirerer.java @@ -0,0 +1,19 @@ +package com.pqt.client.gui.ressources.components.specifics.sale.listeners; + +import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.Sale; +import javafx.event.Event; + +import java.util.Arrays; + +public class SimpleSaleComponentFirerer extends SimpleDisplayerComponentFirerer { + + public SimpleSaleComponentFirerer() { + super(ISaleComponentListener.class); + } + + public void fireComponentClickEvent(Event event, Product product) { + Arrays.stream(listenerList.getListeners(ISaleComponentListener.class)).forEach(l->l.onComponentClickEvent(event, product)); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java new file mode 100644 index 00000000..a2f283e5 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java @@ -0,0 +1,20 @@ +package com.pqt.client.gui.ressources.css; + +public class GUICssTool { + public static String getCssFilePath(){ + //return "/daymode-blue.css"; + return "/nightmode.css"; + } + + public static String getMainModulePaneCssClass() { + return "main-module-pane"; + } + + public static String getIntermediaryPaneStyleClass() { + return "grey-intermediary-pane"; + } + + public static String getTitleTextStyleClass() { + return "label-header"; + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java new file mode 100644 index 00000000..af5f1781 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java @@ -0,0 +1,336 @@ +package com.pqt.client.gui.ressources.strings; + +import com.pqt.core.entities.product.Category; +import com.pqt.core.entities.product.Product; +import com.pqt.core.entities.sale.SaleStatus; +import com.pqt.core.entities.sale.SaleType; +import com.pqt.core.entities.user_account.Account; +import com.pqt.core.entities.user_account.AccountLevel; +import javafx.util.StringConverter; + +import java.text.NumberFormat; +import java.util.EnumSet; + +//TODO faire ça un peu mieux +public class GUIStringTool { + + public static String getValidationButtonLabel() { + return "Valider"; + } + + public static String getConfirmationValidationButtonLabel() { + return "Confirmer"; + } + + public static String getCancelButtonLabel() { + return "Annuler"; + } + + public static String getConfirmationCancelButtonLabel() { + return "Confirmer"; + } + + public static String getCategorytabStockDisplayerTitle() { + return "Produits"; + } + + public static IObjectStringRenderer getDetailledProductStringRenderer(){ + return product->{ + if(product!=null){ + String amountStr; + if(product.getAmountRemaining()<=0){ + amountStr = "OUT OF STOCK"; + }else if(product.getAmountRemaining()>=30){ + amountStr = "30+"; + }else{ + amountStr = Integer.toString(product.getAmountRemaining()); + } + return String.format("%s - %.2f€ (%s)", product.getName(), product.getPrice(), amountStr); + }else + return "null"; + }; + } + + public static IObjectStringRenderer getSimpleProductStringRenderer(){ + return product->{ + if(product!=null) + return String.format("%s - %.2f€", product.getName(), product.getPrice()); + else + return "null"; + }; + } + + public static String getCommandComposerTitleLabel() { + return "Commande"; + } + + public static IObjectWithQuantityStringRenderer getSaleItemStringRenderer(){ + return (product, qte)->String.format("%dx %s", qte, product.getName()); + } + + public static String getPasswordFieldPromptText() { + return "mot de passe"; + } + + public static StringConverter getAccountStringConverter() { + return new StringConverter() { + @Override + public String toString(Account object) { + if(object!=null) + return String.format("%s - (%s)", object.getUsername(), object.getPermissionLevel()); + + return "null"; + } + + @Override + public Account fromString(String string) { + Account reply = new Account(); + + String[] pieces = string.split(" - "); + reply.setUsername(pieces[0]); + if(pieces.length>1) + for(AccountLevel al : EnumSet.allOf(AccountLevel.class)){ + if(al.name().equals(pieces[1])) + reply.setPermissionLevel(al); + } + + return reply; + } + }; + } + + public static String getLogoutButtonLabel() { + return "Déconnexion"; + } + + public static String getLoginButtonLabel() { + return "Connexion"; + } + + public static IObjectStringRenderer getPriceRenderer() { + return price -> NumberFormat.getCurrencyInstance().format(price); + } + + public static String getSaleMakerTextFieldPromptText() { + return "Auteur"; + } + + public static String getSaleMakerTextFieldLabel() { + return "Fait par : "; + } + + public static String getSaleBeneficiaryTextFieldLabel() { + return "Fait pour : "; + } + + public static String getSaleTypeTextFieldLabel() { + return "Type de paiement : "; + } + + public static String getSalePriceTextFieldLabel() { + return "Prix de la commande : "; + } + + public static StringConverter getSaleTypeStringConverter() { + return new StringConverter() { + @Override + public String toString(SaleType object) { + return object.name(); + } + + @Override + public SaleType fromString(String string) { + return EnumSet.allOf(SaleType.class).stream().filter(type->type.name().equals(string)).findFirst().orElse(null); + } + }; + } + + public static String getSalePriceTextFieldPromptText() { + return getPriceRenderer().render(0d); + } + + public static String getCommandValidationErrorMessage() { + return "La commande n'a pas pu être validée"; + } + + public static String getCommandValidationErrorMessage(Throwable cause) { + return "La commande n'a pas pu être validée : "+cause.getMessage(); + } + + public static String getSaleIdLabel() { + return "Numéro de commande : "; + } + + public static String getSaleStatusLabel() { + return "Etat actuel"; + } + + public static IObjectStringRenderer getSaleStatusRenderer() { + return Enum::name; + } + + public static String getOkButtonLabel() { + return "OK"; + } + + public static String getAppTitle() { + return "Client PQT - Gargotte"; + } + + public static String getSideBarCollapseButtonLabel() { + return "Réduire"; + } + + public static String getSideBarExpandButtonLabel() { + return "Menu"; + } + + public static String getSaleGuiModuleName() { + return "Vente"; + } + + public static String getAddButtonLabel() { + return "Ajouter"; + } + + public static String getDetailButtonLabel() { + return "Détail"; + } + + public static String getRemoveButtonLabel() { + return "Supprimer"; + } + + public static String getRefreshButtonLabel() { + return "Rafraichir"; + } + + public static String getProductNameColumnHeader() { + return "Nom"; + } + + public static String getProductCategoryColumnHeader() { + return "Catégorie"; + } + + public static String getProductAmountRemainingColumnHeader() { + return "Stock"; + } + + public static String getProductAmountSoldColumnHeader() { + return "Vendu"; + } + + public static String getProductPriceColumnHeader() { + return "Prix"; + } + + public static String getProductIsSellableColumnHeader() { + return "Vendable"; + } + + public static IObjectStringRenderer getBooleanRenderer() { + return bool->bool?"Oui":"Non"; + } + + public static String getStatGuiModuleName() { + return "Statistiques"; + } + + public static String getProductNameLabel() { + return "Nom : "; + } + + public static String getProductCategoryLabel() { + return "Catégorie : "; + } + + public static String getProductAmountRemainingLabel() { + return "En stock : "; + } + + public static String getProductAmountSoldLabel() { + return "Vendu : "; + } + + public static String getProductSellableLabel() { + return "Vendable : "; + } + + public static String getProductPriceLabel() { + return "Prix : "; + } + + public static StringConverter getCategoryStringConverter() { + return new StringConverter() { + @Override + public String toString(Category object) { + if(object!=null) + return object.getName(); + else + return ""; + } + + @Override + public Category fromString(String string) { + if(string!=null) + return new Category(-1, string); + else + return null; + } + }; + } + + public static String getComponentListTitleLabel() { + return "Composants"; + } + + public static String getAccountGuiModuleName() { + return "Utilisateurs"; + } + + public static IObjectStringRenderer getAccountLevelStringRenderer() { + return level->{ + switch (level){ + case LOWEST: + return "autre"; + case GUEST: + return "Invité"; + case STAFF: + return "Staff"; + case WAITER: + return "Caissier"; + case MASTER: + return "Chef"; + default: + return "unknown"; + } + }; + } + + public static String getAccountListTitleLabel() { + return "Utilisateurs"; + } + + public static String getUsernameLabel() { + return "Nom :"; + } + + public static String getPasswordLabel() { + return "Mot de passe : "; + } + + public static String getUserLevelLabel() { + return "Niveau d'accréditation : "; + } + + public static String getAccountNameColumnHeaderLabel() { + return "Nom d'utilisateur"; + } + + public static String getAccountLevelColumnHeaderLabel() { + return "Niveau d'accréditation"; + } +} + + diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectStringRenderer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectStringRenderer.java new file mode 100644 index 00000000..ebbb8c6a --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectStringRenderer.java @@ -0,0 +1,5 @@ +package com.pqt.client.gui.ressources.strings; + +public interface IObjectStringRenderer { + String render(T obj); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectWithQuantityStringRenderer.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectWithQuantityStringRenderer.java new file mode 100644 index 00000000..52dbbed2 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/IObjectWithQuantityStringRenderer.java @@ -0,0 +1,5 @@ +package com.pqt.client.gui.ressources.strings; + +public interface IObjectWithQuantityStringRenderer { + String render(T obj, int quantity); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/module/account/AccountService.java b/Workspace/client/src/main/java/com/pqt/client/module/account/AccountService.java index c3affffa..9f6c76a0 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/account/AccountService.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/account/AccountService.java @@ -18,7 +18,7 @@ public class AccountService { } - public boolean isAccountLoggedIn(Account account) { + public boolean isCurrentAccountLoggedIn() { return false; } @@ -26,7 +26,7 @@ public class AccountService { } - public void logOutCurrentAccount(String password) { + public void logOutCurrentAccount() { } @@ -42,4 +42,7 @@ public class AccountService { } + public List getAllAccounts() { + return null; + } } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/AccountListenerAdapter.java b/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/AccountListenerAdapter.java index 50243c75..6abd0649 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/AccountListenerAdapter.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/AccountListenerAdapter.java @@ -6,9 +6,16 @@ public class AccountListenerAdapter implements IAccountListener { /** - * @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusChanged(boolean) + * @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusChangedEvent(boolean) */ - public void onAccountStatusChanged(boolean status) { + public void onAccountStatusChangedEvent(boolean status) { + + } + + /** + * @see com.pqt.client.module.account.listeners.IAccountListener#onAccountListChangedEvent() + */ + public void onAccountListChangedEvent() { } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/IAccountListener.java b/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/IAccountListener.java index 7fa6dfef..0de33085 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/IAccountListener.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/account/listeners/IAccountListener.java @@ -4,6 +4,6 @@ import java.util.EventListener; public interface IAccountListener extends EventListener { - public void onAccountStatusChanged(boolean status); - + void onAccountStatusChangedEvent(boolean status); + void onAccountListChangedEvent(); } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleBuilder.java b/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleBuilder.java index 4c550960..a70bac00 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleBuilder.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleBuilder.java @@ -1,5 +1,6 @@ package com.pqt.client.module.sale; +import com.pqt.client.module.stock.StockDao; import com.pqt.core.entities.members.Client; import com.pqt.core.entities.product.Product; import com.pqt.core.entities.sale.Sale; @@ -7,9 +8,7 @@ import com.pqt.core.entities.sale.SaleStatus; import com.pqt.core.entities.sale.SaleType; import com.pqt.core.entities.user_account.Account; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; +import java.util.*; //TODO écrire javadoc public class SaleBuilder { @@ -26,18 +25,40 @@ public class SaleBuilder { } public SaleBuilder addProduct(Product product) { - if(products.containsKey(product)){ - //Check for sufficient stock - if(product.getAmountRemaining() rank0Products = new HashMap<>(); + collectRank0Products(newProduct, requiredAmount, rank0Products); + products.keySet().forEach(oldProduct->collectRank0Products(oldProduct, products.get(oldProduct), rank0Products)); + + return rank0Products.keySet() + .stream() + .filter(rank0Product->rank0Product.getAmountRemaining() collector){ + if(rootProduct.getComponents().isEmpty()){ + if(collector.containsKey(rootProduct)) + collector.replace(rootProduct, collector.get(rootProduct)+rootProductAmount); + else + collector.put(rootProduct, rootProductAmount); + }else{ + rootProduct.getComponents().forEach(product->collectRank0Products(product, rootProductAmount, collector)); + } + } + public SaleBuilder removeProduct(Product product) { if(products.containsKey(product)) { if (products.get(product) == 1) diff --git a/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleService.java b/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleService.java index cdaf60b9..081df440 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleService.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/sale/SaleService.java @@ -6,6 +6,9 @@ import com.pqt.client.module.query.query_callback.IIdQueryCallback; import com.pqt.client.module.sale.listeners.ISaleFirerer; import com.pqt.client.module.sale.listeners.ISaleListener; import com.pqt.client.module.sale.listeners.SimpleSaleFirerer; +import com.pqt.core.entities.sale.SaleType; + +import java.util.List; //TODO écrire javadoc //TODO add log lines @@ -55,4 +58,8 @@ public class SaleService { eventFirerer.removeListener(listener); } + public List getSaleTypes() { + //TODO + return null; + } } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/sale/listeners/ISaleListener.java b/Workspace/client/src/main/java/com/pqt/client/module/sale/listeners/ISaleListener.java index ddb44c48..8369a112 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/sale/listeners/ISaleListener.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/sale/listeners/ISaleListener.java @@ -1,15 +1,13 @@ package com.pqt.client.module.sale.listeners; -import com.pqt.core.entities.sale.Sale; - import java.util.EventListener; public interface ISaleListener extends EventListener { - public abstract void onSaleValidationSuccess(long saleId); + void onSaleValidationSuccess(long saleId); - public abstract void onSaleValidationError(long saleId, Throwable cause); + void onSaleValidationError(long saleId, Throwable cause); - public abstract void onSaleValidationRefused(long saleId, Throwable cause); + void onSaleValidationRefused(long saleId, Throwable cause); } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/stock/StockDao.java b/Workspace/client/src/main/java/com/pqt/client/module/stock/StockDao.java index d682f84f..08439d66 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/stock/StockDao.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/stock/StockDao.java @@ -33,12 +33,8 @@ public class StockDao { } public synchronized Product getProduct(final int id) { - Optional match = products.stream().filter((product->product.getId()==id)).findFirst(); - if(match.isPresent()) - return match.get(); - - return null; - } + return products.stream().filter((product->product.getId()==id)).findFirst().orElse(null); + } public void refreshProductList() { QueryExecutor.INSTANCE.execute(QueryFactory.newStockQuery(), new IStockQueryCallback() { diff --git a/Workspace/client/src/main/java/com/pqt/client/module/stock/StockService.java b/Workspace/client/src/main/java/com/pqt/client/module/stock/StockService.java index 95644e61..8c2e67aa 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/stock/StockService.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/stock/StockService.java @@ -13,7 +13,7 @@ public class StockService { private StockDao dao; - private StockService() { + public StockService() { dao = new StockDao(); } @@ -39,7 +39,8 @@ public class StockService { /** * Accesseur de la liste des produits actuellement en vente. *

- * La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et {@link #refreshProductList()} pour la mettre à jour. + * La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et + * {@link #refreshProductList()} pour la mettre à jour. * * @return Liste des produits en vente. */ @@ -47,6 +48,35 @@ public class StockService { return dao.getProducts(); } + /** + * Récupère la liste des produits n'étant pas {@code product} et n'étant pas composé de {@code product}. + * Les composants sont récursivements vérifiés pour que ces derniers valident aussi ces deux conditions. + *

+ * La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et + * {@link #refreshProductList()} pour la mettre à jour. + * + * @param product produit à exclure des résultats. + * @return Liste de produit n'étant pas et ne contenant pas {@code product}. + */ + public List getProductsExcluding(Product product) { + return dao.getProducts(); + } + + private boolean contains(Product container, Product contained){ + if(container==null || contained==null) + return false; + if(container.equals(contained)) + return true; + + if(container.getComponents()!=null) + return container.getComponents() + .stream() + .filter(component->contains(component, contained)) + .count()>0; + + return false; + } + /** * Accesseur récupérant un unique produit présent dans les stocks en se basant sur son id. * @@ -100,5 +130,4 @@ public class StockService { public void removeListener(IStockListener listener) { dao.removeListener(listener); } - } diff --git a/Workspace/client/src/main/java/com/pqt/client/module/stock/UpdateBuilder.java b/Workspace/client/src/main/java/com/pqt/client/module/stock/UpdateBuilder.java index 36826f26..f471916b 100644 --- a/Workspace/client/src/main/java/com/pqt/client/module/stock/UpdateBuilder.java +++ b/Workspace/client/src/main/java/com/pqt/client/module/stock/UpdateBuilder.java @@ -16,20 +16,23 @@ public class UpdateBuilder { toModify = new HashMap<>(); } - public void addProduct(Product product) { + public UpdateBuilder addProduct(Product product) { if(!toAdd.contains(product)){ toAdd.add(product); } + return this; } - public void removeProduct(Product product) { + public UpdateBuilder removeProduct(Product product) { if(toRemove.contains(product)){ toRemove.remove(product); } + return this; } - public void modifyProduct(Product oldVersion, Product newVersion) { + public UpdateBuilder modifyProduct(Product oldVersion, Product newVersion) { toModify.put(oldVersion, newVersion); + return this; } public List build() { diff --git a/Workspace/client/src/main/resources/nightmode.css b/Workspace/client/src/main/resources/nightmode.css new file mode 100644 index 00000000..a33217d2 --- /dev/null +++ b/Workspace/client/src/main/resources/nightmode.css @@ -0,0 +1,235 @@ +.root { + -fx-background-color: #1d1d1d; +} + +.label { + -fx-font-size: 11pt; + -fx-font-family: "Segoe UI Semibold"; + -fx-text-fill: white; + -fx-opacity: 0.8; +} + +.label-bright { + -fx-font-size: 11pt; + -fx-font-family: "Segoe UI Semibold"; + -fx-text-fill: white; + -fx-opacity: 1; +} + +.label-header { + -fx-font-size: 25pt; + -fx-font-family: "Segoe UI"; + -fx-text-fill: white; + -fx-opacity: 1; +} + +.tab { + -fx-background-color: #3a3a3a; +} + +.tab-label { + -fx-text-fill: white; +} + +.tab:selected { + -fx-background-color: #4d4d4d; +} + +.tab-pane *.tab-header-background { + -fx-background-color: #1d1d1d; +} + +.list-view { + -fx-control-inner-background: #1d1d1d; + -fx-control-inner-background-alt: #333333; + -fx-padding: 5; + -fx-border-width: 0px; +} + +.list-view .list-cell .label{ + -fx-font-size: 20pt; + -fx-font-family: "Segoe UI Light"; + -fx-text-fill: white; + -fx-alignment: center-left; +} + +.list-view:focused .list-cell:filled:focused:selected { + -fx-background-color: -fx-focus-color; +} +.list-cell:highlighted{ + -fx-text-fill: #cc7a00; + -fx-border-width: 1px; + -fx-border-color: white; +} + +.table-view { + -fx-base: #1d1d1d; + -fx-control-inner-background: #1d1d1d; + -fx-control-inner-background-alt: #333333; + -fx-table-cell-border-color: transparent; + -fx-table-header-border-color: transparent; + -fx-padding: 5; +} + +.table-view .column-header-background { + -fx-background-color: transparent; +} + +.table-view .column-header, .table-view .filler { + -fx-size: 35px; + -fx-border-width: 0 0 1 0; + -fx-background-color: transparent; + -fx-border-color: + transparent + transparent + derive(-fx-base, 80%) + transparent; + -fx-border-insets: 0 10 1 0; +} + +.table-view .column-header .label { + -fx-font-size: 20pt; + -fx-font-family: "Segoe UI Light"; + -fx-text-fill: white; + -fx-alignment: center-left; + -fx-opacity: 1; +} + +.table-view .table-row-cell { + -fx-control-inner-background: #1d1d1d; + -fx-control-inner-background-alt: #333333; +} + +.table-view .table-row-cell:stock-out { + -fx-control-inner-background: #4d0000; + -fx-control-inner-background-alt: #4d0000; +} + +.table-view .table-row-cell:stock-low { + -fx-control-inner-background: #4d2e00; + -fx-control-inner-background-alt: #4d2e00; +} + +.table-view .table-row-cell:stock-high { + -fx-control-inner-background: #1a3300; + -fx-control-inner-background-alt: #1a3300; +} + +.table-view:focused .table-row-cell:filled:focused:selected { + -fx-background-color: -fx-focus-color; +} + +.grid-pane { + -fx-hgap: 10; + -fx-vgap: 10; +} + +.context-menu { + -fx-background-color: derive(#1d1d1d,5%); +} +.text-field, .password-field, .choice-box, .text-area, .combo-box, .button { + -fx-font-size: 12pt; + -fx-font-family: "Segoe UI Semibold"; + -fx-pref-width: 150; + -fx-pref-height: 30; + -fx-background-color: #1d1d1d; + -fx-border-color: #e2e2e2; + -fx-border-width: 2; + -fx-text-fill: #d8d8d8; +} + +.button:hover { + -fx-background-color: #3a3a3a; +} + +.button:pressed, .button:default:hover:pressed { + -fx-background-color: white; + -fx-text-fill: #1d1d1d; +} + +.button:focused { + -fx-border-color: white, white; + -fx-border-width: 1, 1; + -fx-border-style: solid; + -fx-border-radius: 0, 0; + -fx-border-insets: 1 1 1 1, 0; +} + +.button:disabled, .button:default:disabled { + -fx-opacity: 0.4; + -fx-background-color: #1d1d1d; + -fx-text-fill: white; +} + +.button:default { + -fx-background-color: -fx-focus-color; + -fx-text-fill: #ffffff; +} + +.button:default:hover { + -fx-background-color: derive(-fx-focus-color,30%); +} + +.text-area .content { + -fx-background-color: #1d1d1d; + -fx-padding: 15 15 15 15; +} + +#stat-screen-text-area { + -fx-border-width: 0; +} + +.progress-indicator { + -fx-pref-width: 50; + -fx-pref-height: 50; +} + +.grey-intermediary-pane { + -fx-background-color: #1d1d1d; + -fx-opacity: 85%; +} + +.main-module-pane { + -fx-padding: 10 10 10 10; +} + +.validator { + -fx-padding: 10 10 10 10; + -fx-hgap: 10; + -fx-vgap: 10; +} +.validator .button{ + -fx-pref-width: 150; + -fx-pref-height: 50; +} + +.sidebar { + -fx-background-color: #2e2e2e; + -fx-padding: 5 22 5 22; + -fx-border-color: whitesmoke; + -fx-border-width: 2; + -fx-background-radius: 0; + -fx-background-insets: 0 0 0 0, 0, 1, 2; + -pqt-expanded-width : 195px; +} + +.tool-bar { + -fx-background-color: #2e2e2e; + -fx-padding: 5 5 5 5; + -fx-background-radius: 0; + -fx-background-insets: 0 0 0 0, 0, 1, 2; +} + +.toast-text{ + -fx-font: 50px "Impact"; + -fx-fill: whitesmoke; +} + +.toast-pane { + -fx-background-radius: 10px; + -fx-background-color: rgba(0, 0, 0, 0.4); + -fx-border-width: 2px; + -fx-border-color: whitesmoke; + -fx-border-radius: 6px; + -fx-padding: 25px; +} \ No newline at end of file diff --git a/Workspace/core/core.iml b/Workspace/core/core.iml new file mode 100644 index 00000000..192d284a --- /dev/null +++ b/Workspace/core/core.iml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java b/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java index 9eac8abd..939c3bda 100644 --- a/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java +++ b/Workspace/core/src/main/java/com/pqt/core/communication/GSonMessageToolFactory.java @@ -3,13 +3,6 @@ package com.pqt.core.communication; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; -import com.pqt.core.entities.members.PqtMember; -import com.pqt.core.entities.members.PqtMemberType; -import com.pqt.core.entities.messages.Message; -import com.pqt.core.entities.messages.MessageType; -import com.pqt.core.entities.product.Product; -import com.pqt.core.entities.product.ProductUpdate; -import com.pqt.core.entities.sale.Sale; import java.lang.reflect.Type; import java.util.ArrayList; diff --git a/Workspace/core/src/main/java/com/pqt/core/entities/members/Client.java b/Workspace/core/src/main/java/com/pqt/core/entities/members/Client.java index a4498012..aaa92a4d 100644 --- a/Workspace/core/src/main/java/com/pqt/core/entities/members/Client.java +++ b/Workspace/core/src/main/java/com/pqt/core/entities/members/Client.java @@ -27,21 +27,6 @@ public class Client extends PqtMember{ this.address = address; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Client client = (Client) o; - - return address.equals(client.address) && id==client.id && type.equals(client.type); - } - - @Override - public int hashCode() { - return address.hashCode() + type.hashCode() + Integer.class.cast(id); - } - @Override public int hashCode() { return Objects.hash(super.hashCode(), address); diff --git a/Workspace/core/src/main/java/com/pqt/core/entities/product/Product.java b/Workspace/core/src/main/java/com/pqt/core/entities/product/Product.java index ec5d5074..6c40e894 100644 --- a/Workspace/core/src/main/java/com/pqt/core/entities/product/Product.java +++ b/Workspace/core/src/main/java/com/pqt/core/entities/product/Product.java @@ -6,7 +6,7 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Objects; - +//TODO faire en sorte que les composés reprennent les qté dispo des composants /** * Created by Notmoo on 18/07/2017. */ @@ -123,6 +123,7 @@ public class Product implements ILoggable, Serializable{ return this.id == other.id && Objects.equals(this.name, other.name) && Objects.equals(this.components, other.components) - && Objects.equals(this.category, other.category); + && Objects.equals(this.category, other.category) + && Objects.equals(this.price, other.price); } } diff --git a/Workspace/core/src/main/java/com/pqt/core/entities/user_account/Account.java b/Workspace/core/src/main/java/com/pqt/core/entities/user_account/Account.java index be090371..f3d7ad34 100644 --- a/Workspace/core/src/main/java/com/pqt/core/entities/user_account/Account.java +++ b/Workspace/core/src/main/java/com/pqt/core/entities/user_account/Account.java @@ -23,6 +23,10 @@ public class Account implements ILoggable, Serializable { this.permissionLevel = permissionLevel; } + public Account(Account account) { + this(account.getUsername(), account.getPassword(), account.getPermissionLevel()); + } + public String getUsername() { return username; } @@ -49,7 +53,7 @@ public class Account implements ILoggable, Serializable { @Override public int hashCode() { - return Objects.hash(id, username, passwordHash, permissionLevel); + return Objects.hash(username, password, permissionLevel); } @Override @@ -61,9 +65,8 @@ public class Account implements ILoggable, Serializable { return false; Account acc = Account.class.cast(obj); - return this.id == acc.id - && Objects.equals(this.username, acc.username) - && Objects.equals(this.passwordHash, acc.passwordHash) + return Objects.equals(this.username, acc.username) + && Objects.equals(this.password, acc.password) && Objects.equals(this.permissionLevel, acc.permissionLevel); } } diff --git a/Workspace/server/server.iml b/Workspace/server/server.iml new file mode 100644 index 00000000..3284aafa --- /dev/null +++ b/Workspace/server/server.iml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file