package com.pam.codenamehippie.ui; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import com.pam.codenamehippie.R; import com.pam.codenamehippie.controleur.validation.Validateur; import com.pam.codenamehippie.controleur.validation.ValidateurDeChampTexte; import com.pam.codenamehippie.controleur.validation.ValidateurDeSpinner; import com.pam.codenamehippie.controleur.validation.ValidateurObserver; import com.pam.codenamehippie.http.exception.HttpReponseException; import com.pam.codenamehippie.modele.AlimentaireModele; import com.pam.codenamehippie.modele.DescriptionModel; import com.pam.codenamehippie.modele.OrganismeModele; import com.pam.codenamehippie.modele.TypeAlimentaireModele; import com.pam.codenamehippie.modele.UtilisateurModele; import com.pam.codenamehippie.modele.depot.AlimentaireModeleDepot; import com.pam.codenamehippie.modele.depot.AlimentaireModeleDepot.PeuplerListesDeSpinnerListener; import com.pam.codenamehippie.modele.depot.DepotManager; import com.pam.codenamehippie.modele.depot.ObservateurDeDepot; import com.pam.codenamehippie.ui.adapter.HippieSpinnerAdapter; import com.pam.codenamehippie.ui.adapter.TypeAlimentaireModeleSpinnerAdapter; import com.pam.codenamehippie.ui.view.dialog.CalendarPickerViewDialogFragment; import com.pam.codenamehippie.ui.view.dialog.CalendarPickerViewDialogFragment.OnDismissListener; import com.squareup.timessquare.CalendarPickerView.OnDateSelectedListener; import java.io.IOException; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Cette classe permet à un donneur d'ajouter et modifier des produits à la base de données * via l'interface utilisateur. La date du jour sera utilisée comme date de disponibilité. * Si un produit n'a pas de date de péremption, la date sera mise à null du côté du serveur. */ public class AjoutMarchandiseActivity extends HippieActivity implements ValidateurObserver, PeuplerListesDeSpinnerListener, ObservateurDeDepot<AlimentaireModele>, OnDateSelectedListener, OnDismissListener { public static final String MODELE_ID = "id"; private static final String SELECTED_SPINNER_TYPE_POSITION = "position_type"; private static final String SELECTED_SPINNER_UNITE_POSITION = "position_unite"; private static final String SAVED_MODEL = "modele"; private ValidateurDeChampTexte validateurNom; private boolean nomEstValide; private ValidateurDeChampTexte validateurDescription; private boolean descriptionEstValide; private ValidateurDeChampTexte validateurQuantite; private boolean quantiteEstValide; private ValidateurDeChampTexte validateurValeur; private boolean valeurEstValide; private ValidateurDeSpinner validateurSpinnerUniteMarchandise; private ValidateurDeSpinner validateurSpinnerTypeMarchandise; private CalendarPickerViewDialogFragment datePeremptionFragment; private Button bAjoutMarchandise; private boolean spinnerUniteMarchandiseEstValide; private boolean spinnerTypeMarchandiseEstValide; private boolean datePeremptionEstValide; private TextView datePicker; private TextView tvDatePeremption; // Id de alimentaire pour sélection route modifier ou ajouter private AlimentaireModele modele; // Id de l'organisme dont l'utilisateur est membre. private Integer organismeId; private int selectedSpinnerUnitePosition; private int selectedSpinnerTypePosition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.setContentView(R.layout.ajout_marchandise); // ********************************************************************************* // Chaque EditText passe par le ValidateurDeChampTexte et doit répondre à certains * // critères dont la longeur max et si le champ est requis * // ********************************************************************************* EditText etNomMarchandise = (EditText) this.findViewById(R.id.etNomMarchandise); this.validateurNom = ValidateurDeChampTexte.newInstance(this, etNomMarchandise, true, ValidateurDeChampTexte .NOM_ALIMENTAIRE_LONGUEUR_MAX); this.validateurNom.registerObserver(this); EditText etDescMarchandise = (EditText) this.findViewById(R.id.etDescMarchandise); this.validateurDescription = ValidateurDeChampTexte.newInstance(this, etDescMarchandise, true, ValidateurDeChampTexte .DESCRIPTION_ALIMENTAIRE_LONGUEUR_MAX); this.validateurDescription.registerObserver(this); EditText etQteeMarchandise = (EditText) this.findViewById(R.id.etQteeMarchandise); this.validateurQuantite = ValidateurDeChampTexte.newInstance(this, etQteeMarchandise, true, ValidateurDeChampTexte .QUANTITE_ALIMENTAIRE_LONGUEUR_MAX); this.validateurQuantite.setEstNumerique(true); this.validateurQuantite.registerObserver(this); EditText etValeurMarchandise = (EditText) this.findViewById(R.id.etValeurMarchandise); this.validateurValeur = ValidateurDeChampTexte.newInstance(this, etValeurMarchandise, true, ValidateurDeChampTexte .VALEUR_ALIMENTAIRE_LONGUEUR_MAX); this.validateurValeur.setEstNumerique(true); this.validateurValeur.registerObserver(this); // *************************************************************************************** // Chaque Spinner passe par le ValidateurDeSpinner et le choix doit être différent de la * // valeur par défaut ("Faites votre choix...") pour qu'il soit valide * // *************************************************************************************** Spinner spinnerUniteMarchandise = (Spinner) this.findViewById(R.id.spinnerUniteMarchandise); this.validateurSpinnerUniteMarchandise = ValidateurDeSpinner.newInstance(spinnerUniteMarchandise); this.validateurSpinnerUniteMarchandise.registerObserver(this); // Binder les descriptions d'uniteMarchandise au spinnerUniteMarchandise HippieSpinnerAdapter uniteAdapter = new HippieSpinnerAdapter(this); spinnerUniteMarchandise.setAdapter(uniteAdapter); Spinner spinnerTypeMarchandise = (Spinner) this.findViewById(R.id.spinnerTypeMarchandise); this.validateurSpinnerTypeMarchandise = ValidateurDeSpinner.newInstance(spinnerTypeMarchandise); this.validateurSpinnerTypeMarchandise.registerObserver(this); // Binder les descriptions de typeMarchandise au spinnerTypeMarchandise TypeAlimentaireModeleSpinnerAdapter typeAdapter = new TypeAlimentaireModeleSpinnerAdapter(this); spinnerTypeMarchandise.setAdapter(typeAdapter); this.datePicker = (TextView) this.findViewById(R.id.datePicker); this.tvDatePeremption = (TextView) this.findViewById(R.id.tvDatePeremption); TextView tvAjoutMarchandise = (TextView) this.findViewById(R.id.tvAjoutMarchandise); tvAjoutMarchandise.setText(R.string.ajouter_marchandise); this.bAjoutMarchandise = (Button) this.findViewById(R.id.bAjoutMarchandise); this.bAjoutMarchandise.setText(R.string.bouton_ajouter); // Provient de l'Intent de ListeMesDonsActivity lors du clic sur modifier un produit Bundle bundle = this.getIntent().getExtras(); // Si le Bundle n'est pas null, il s'agit d'une modification à faire sur un don. int id = 0; if (bundle != null) { // Modifier le TextView pour signifier une modification tvAjoutMarchandise.setText(R.string.modifier_marchandise); this.bAjoutMarchandise.setText(R.string.bouton_modifier); this.bAjoutMarchandise.setEnabled(true); // Obtenir le id du produit à modifier id = bundle.getInt(MODELE_ID, 0); } if (savedInstanceState != null) { this.selectedSpinnerTypePosition = savedInstanceState.getInt(SELECTED_SPINNER_TYPE_POSITION, 0); this.selectedSpinnerUnitePosition = savedInstanceState.getInt(SELECTED_SPINNER_UNITE_POSITION, 0); String json = savedInstanceState.getString(SAVED_MODEL); if (json != null) { Log.d("Test", json); this.modele = DepotManager.getInstance().getAlimentaireModeleDepot().fromJson(json); } } this.modele = (this.modele == null) ? new AlimentaireModele() : this.modele; UtilisateurModele uc = this.authentificateur.getUtilisateur(); OrganismeModele org = (uc != null) ? uc.getOrganisme() : null; this.modele.setId(id).setOrganisme(org); } @Override protected void onResume() { super.onResume(); AlimentaireModeleDepot depot = DepotManager.getInstance().getAlimentaireModeleDepot(); depot.peuplerLesListesDeSpinners(this); if (this.modele.getId() != 0) { depot.rechercherParId(this.modele.getId()); } this.afficherModele(this.modele); this.validateurNom.onResume(); this.validateurDescription.onResume(); this.validateurQuantite.onResume(); this.validateurValeur.onResume(); } @Override protected void onPause() { super.onPause(); this.validateurNom.onPause(); this.validateurDescription.onPause(); this.validateurQuantite.onPause(); this.validateurValeur.onPause(); this.validateurSpinnerUniteMarchandise.onPause(); this.validateurSpinnerTypeMarchandise.onPause(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt(SELECTED_SPINNER_UNITE_POSITION, this.validateurSpinnerUniteMarchandise.getSelectedItemPosition()); outState.putInt(SELECTED_SPINNER_TYPE_POSITION, this.validateurSpinnerTypeMarchandise.getSelectedItemPosition()); if (this.modele != null) { String json = DepotManager.getInstance().getAlimentaireModeleDepot().toJson(this.modele); outState.putString(SAVED_MODEL, json); } } /** * Méthode pour valider les différentes composantes de l'interface utilisateur selon * le type de validation et les valeurs inscrites. * * @param validateur * Type de validateur. Ex: ValidateurDeChampTexte, ValidateurDeSpinner etc... * @param estValide * Retourne True or False selon la validation. */ @Override public void enValidant(Validateur validateur, boolean estValide) { if (validateur.equals(this.validateurNom)) { this.nomEstValide = estValide; if (estValide) { this.modele.setNom(this.validateurNom.getTextString()); } } else if (validateur.equals(this.validateurDescription)) { this.descriptionEstValide = estValide; } else if (validateur.equals(this.validateurQuantite)) { this.quantiteEstValide = (estValide); } else if (validateur.equals(this.validateurValeur)) { this.valeurEstValide = estValide; } else if (validateur.equals(this.validateurSpinnerUniteMarchandise)) { this.spinnerUniteMarchandiseEstValide = estValide; } else if (validateur.equals(this.validateurSpinnerTypeMarchandise)) { // Mettre invisible le DatePicker si un produit est non perissable TypeAlimentaireModele item = (TypeAlimentaireModele) this.validateurSpinnerTypeMarchandise.getSelectedItem(); if ((item != null && item.getEstPerissable()) || this.validateurSpinnerTypeMarchandise.getSelectedItemId() == 0) { this.tvDatePeremption.setVisibility(View.VISIBLE); this.datePicker.setVisibility(View.VISIBLE); } else { this.tvDatePeremption.setVisibility(View.GONE); this.datePicker.setVisibility(View.GONE); } this.spinnerTypeMarchandiseEstValide = estValide; } // Check si on fait parti d'un organisme... // FIXME: Ce check devrait etre fait au serveur. boolean hasOrganismeid = (this.modele.getOrganisme() != null); // Mettre le bouton pour ajouter la marchandise actif si tous les champs requis // respecte les conditions des validateurs. /* this.bAjoutMarchandise.setEnabled(this.nomEstValide && this.descriptionEstValide && this.quantiteEstValide && this.valeurEstValide && this.spinnerUniteMarchandiseEstValide && this.spinnerTypeMarchandiseEstValide && hasOrganismeid); */ this.bAjoutMarchandise.setEnabled(true); } @Override public void surDebut() { this.afficherLaProgressBar(); } @Override public void surDebutDeRequete() { this.afficherLaProgressBar(); } @Override public void surChangementDeDonnees(List<AlimentaireModele> modeles) { if ((modeles != null) && (modeles.size() != 0)) { this.modele = modeles.get(0); if (this.modele != null) { this.afficherModele(this.modele); } } } @Override public void surFinDeRequete() { this.cacherLaProgressbar(); } @Override public void surErreur(IOException e) { Snackbar snackbar; if (e instanceof HttpReponseException) { switch (((HttpReponseException) e).getCode()) { case 404: snackbar = Snackbar.make(this.viewSwitcher, R.string.error_http_404, Snackbar.LENGTH_SHORT); break; case 500: snackbar = Snackbar.make(this.viewSwitcher, R.string.error_http_500, Snackbar.LENGTH_SHORT); break; default: snackbar = Snackbar.make(this.viewSwitcher, R.string.error_connection, Snackbar.LENGTH_SHORT); break; } } else { snackbar = Snackbar.make(this.viewSwitcher, R.string.error_connection, Snackbar.LENGTH_SHORT); } snackbar.show(); } @Override public void surListeUnite(ArrayList<DescriptionModel> items) { Spinner spinner = this.validateurSpinnerUniteMarchandise.getSpinner(); HippieSpinnerAdapter adapter = ((HippieSpinnerAdapter) spinner.getAdapter()); adapter.setItems(items); Bundle bundle = this.getIntent().getExtras(); // Récupérer la position du spinnerUniteMarchandise selon la description si mode modifier if (bundle != null) { String s = bundle.getString("unite"); if (s != null) { for (int i = 0; i < adapter.getCount(); i++) { String description = adapter.getItem(i).getDescription(); if (s.equalsIgnoreCase(description)) { spinner.setSelection(i); break; } } } } else { spinner.setSelection(this.selectedSpinnerUnitePosition); } } @Override public void surListeType(ArrayList<TypeAlimentaireModele> items) { Spinner spinner = this.validateurSpinnerTypeMarchandise.getSpinner(); TypeAlimentaireModeleSpinnerAdapter adapter = ((TypeAlimentaireModeleSpinnerAdapter) spinner.getAdapter()); adapter.setItems(items); // Récupérer la position du spinnerTypeMarchandise selon la description si mode modifier Bundle bundle = this.getIntent().getExtras(); if (bundle != null) { String s = bundle.getString("typeAlimentaire"); if (s != null) { for (int i = 0; i < adapter.getCount(); i++) { String description = adapter.getItem(i).getDescription(); if (s.equalsIgnoreCase(description)) { spinner.setSelection(i); break; } } } } else { spinner.setSelection(this.selectedSpinnerTypePosition); } } @Override public void surFin() { this.cacherLaProgressbar(); this.validateurSpinnerUniteMarchandise.onResume(); this.validateurSpinnerTypeMarchandise.onResume(); } @Override public void onDateSelected(Date date) { DateFormat df = android.text.format.DateFormat.getLongDateFormat(this); this.datePicker.setText(df.format(date)); if (this.modele != null) { this.modele.setDatePeremption(date); } } @Override public void onDismiss(CalendarPickerViewDialogFragment fragment, DialogInterface dialog) { this.onDateSelected(fragment.dateSelectionee()); } @Override public void onDateUnselected(Date date) { } public void surDatePickerClick(View v) { if (this.datePeremptionFragment == null) { Date date = (this.modele.getDatePeremption() != null) ? this.modele.getDatePeremption() : new Date(); this.datePeremptionFragment = this.newDatePicker(date); } if (!this.datePeremptionFragment.isVisible()) { this.datePeremptionFragment.show(this.getSupportFragmentManager(), null); } } /** * Méthode pour soumettre une requête afin d'ajouter un produit dans la base de données sur le * serveur. * * @param v * Vue qui a été cliquêe. */ public void soumettreMarchandise(final View v) { DescriptionModel typeAlimentaire = ((DescriptionModel) this.validateurSpinnerTypeMarchandise.getSelectedItem()); String typeAlimentaireId = String.valueOf(this.validateurSpinnerTypeMarchandise.getSelectedItemId()); String marchandiseUniteId = String.valueOf(this.validateurSpinnerUniteMarchandise.getSelectedItemId()); // FIXME: Gérer l'état de marchandise. On mets 3(neuf) en attendant this.modele.setNom(this.validateurNom.getTextString()) .setDescription(this.validateurDescription.getTextString()) .setValeur(Double.parseDouble(this.validateurValeur.getTextString())) .setQuantite(Double.parseDouble(this.validateurQuantite.getTextString())) .setUniteDeQuantite(marchandiseUniteId) .setEtat("3") .setTypeAlimentaire(typeAlimentaireId); if (((TypeAlimentaireModele) this.validateurSpinnerTypeMarchandise.getSelectedItem()) .getEstPerissable() == false && this.modele.getDatePeremption() == null) { this.modele.setDatePeremption(new Date()); } AlimentaireModeleDepot depot = DepotManager.getInstance().getAlimentaireModeleDepot(); if ((this.modele.getId() != null) && (this.modele.getId() != 0)) { // Si le id est différent de null, il s'agit d'une modification sur le produit // et il faut agir en conséquence. depot.modifierModele(this.modele, new Runnable() { @Override public void run() { Snackbar snackbar = Snackbar.make(v, R.string.msg_produit_modifie, Snackbar.LENGTH_SHORT); snackbar.setCallback(new Snackbar.Callback() { @Override public void onDismissed(Snackbar snackbar, int event) { if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) { AjoutMarchandiseActivity.this.finish(); } } }).show(); } }); } else { depot.ajouterModele(this.modele, new Runnable() { @Override public void run() { // C'est un ajout de produit Snackbar.make(v, R.string.msg_produit_ajoute, Snackbar.LENGTH_SHORT) .show(); AjoutMarchandiseActivity.this.effacerFormulaire(); } }); } } /** * Méthode pour réinitialiser les champs du formulaire. */ private void effacerFormulaire() { this.validateurNom.setText(null); this.validateurDescription.setText(null); this.validateurQuantite.setText(null); this.validateurSpinnerUniteMarchandise.setSelectedItemId(0); this.validateurValeur.setText(null); this.validateurSpinnerTypeMarchandise.setSelectedItemId(0); this.tvDatePeremption.setVisibility(View.VISIBLE); this.datePicker.setVisibility(View.VISIBLE); this.onDateSelected(new Date()); } private void afficherModele(@NonNull AlimentaireModele modele) { this.validateurNom.setText(modele.getNom()); this.validateurDescription.setText(modele.getDescription()); this.validateurQuantite.setText(modele.getQuantite().toString()); this.validateurValeur.setText(modele.getValeur().toString()); DateFormat df = android.text.format.DateFormat.getLongDateFormat(this); Date date = (modele.getDatePeremption() != null) ? modele.getDatePeremption() : new Date(); this.datePicker.setText(df.format(date)); this.datePeremptionFragment = this.newDatePicker(date); } private CalendarPickerViewDialogFragment newDatePicker(@NonNull Date date) { return CalendarPickerViewDialogFragment.assigneUnNouveauFragment() .avecCetteDateSelectionnee(date) .pisCestTout() .setOnDateSelectedListener(this) .setOnDismissListener(this); } }