From b3d94ad038d20f36941314aaafe2f23226d9d4ae Mon Sep 17 00:00:00 2001 From: OnlyPapy98 Date: Fri, 12 Dec 2025 17:55:12 +0100 Subject: [PATCH] 70% of features done! --- app/build.gradle.kts | 5 + app/src/main/AndroidManifest.xml | 4 + .../com/example/quiz/AnnulationTicket.java | 49 +- .../java/com/example/quiz/BetValidation.java | 216 +++--- .../main/java/com/example/quiz/Caisse.java | 8 + .../java/com/example/quiz/DerniersParis.java | 105 +++ .../com/example/quiz/ListOfTypeOfBets.java | 8 +- .../main/java/com/example/quiz/PageQuiz.java | 2 + .../java/com/example/quiz/ScannerDialog.java | 137 ++++ app/src/main/java/com/example/quiz/Sold.java | 52 +- .../java/com/example/quiz/SoldByCourse.java | 58 +- .../main/java/com/example/quiz/WinTicket.java | 7 + .../quiz/data/adapter/BetsAdapter.java | 9 +- .../quiz/data/adapter/LastBetsAdapter.java | 120 ++++ .../com/example/quiz/data/model/Pari.java | 23 +- .../quiz/data/model/dtos/PariCourseDto.java | 33 + .../example/quiz/data/remote/ApiClient.java | 2 +- .../example/quiz/data/remote/ApiService.java | 15 + .../quiz/data/repository/PariRepository.java | 108 +++ .../example/quiz/viewModel/PariViewModel.java | 38 + .../main/res/drawable/ic_couple_gagnant.xml | 540 ++++++++++++++ app/src/main/res/drawable/ic_couple_place.xml | 657 ++++++++++++++++++ app/src/main/res/drawable/ic_quarte.xml | 435 ++++++++++++ app/src/main/res/drawable/ic_quinte_plus.xml | 213 ++++++ app/src/main/res/drawable/ic_tierce.xml | 297 ++++++++ .../res/layout/fragment_annulation_ticket.xml | 1 + .../res/layout/fragment_bet_validation.xml | 342 ++++----- .../res/layout/fragment_derniers_paris.xml | 14 + app/src/main/res/layout/fragment_scan.xml | 18 + .../main/res/layout/fragment_win_ticket.xml | 1 + app/src/main/res/layout/last_bets_item.xml | 102 +++ 31 files changed, 3334 insertions(+), 285 deletions(-) create mode 100644 app/src/main/java/com/example/quiz/DerniersParis.java create mode 100644 app/src/main/java/com/example/quiz/ScannerDialog.java create mode 100644 app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java create mode 100644 app/src/main/res/drawable/ic_couple_gagnant.xml create mode 100644 app/src/main/res/drawable/ic_couple_place.xml create mode 100644 app/src/main/res/drawable/ic_quarte.xml create mode 100644 app/src/main/res/drawable/ic_quinte_plus.xml create mode 100644 app/src/main/res/drawable/ic_tierce.xml create mode 100644 app/src/main/res/layout/fragment_derniers_paris.xml create mode 100644 app/src/main/res/layout/fragment_scan.xml create mode 100644 app/src/main/res/layout/last_bets_item.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6d5073..d56072f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,6 +43,11 @@ android { dependencies { implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar")))) implementation(libs.swiperefreshlayout) + implementation("androidx.camera:camera-camera2:1.2.3") + implementation("androidx.camera:camera-lifecycle:1.2.3") + implementation("androidx.camera:camera-view:1.2.3") + implementation("androidx.camera:camera-core:1.2.3") + implementation("com.google.mlkit:barcode-scanning:17.2.0") implementation(libs.retrofit) implementation(libs.okhttp) implementation(libs.logging.interceptor) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8e54420..ca0b953 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,9 @@ + + + @@ -62,6 +65,7 @@ android:name="com.google.android.geo.API_KEY" android:value="YOUR_API_KEY" /> + { getActivity().onBackPressed(); }); + + binding.scanTicketBtn.setOnClickListener(v -> { + ScannerDialog scannerDialog = new ScannerDialog(); + scannerDialog.setOnBarcodeScannedListener(code -> { + binding.referenceTicket.setText(code); + }); + scannerDialog.show(getParentFragmentManager(), "scanner"); + }); + + binding.annuleTicketBtn.setOnClickListener(v->{ + String reference = binding.referenceTicket.getText().toString(); + if(reference.isEmpty()){ + Toast.makeText(getContext(),"Entrez la référence du ticket", Toast.LENGTH_SHORT).show(); + return; + } + viewModel.annulerPari(reference).observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(Result pariResult) { + switch (pariResult.status){ + case LOADING:{ + Toast.makeText(getContext(), "Chargement...", Toast.LENGTH_SHORT).show(); + break; + } + case ERROR:{ + Toast.makeText(getContext(), pariResult.message, Toast.LENGTH_SHORT).show(); + break; + } + case SUCCESS:{ + Toast.makeText(getContext(), "Ticket annulé avec succès", Toast.LENGTH_SHORT).show(); + binding.referenceTicket.setText(""); + } + } + } + }); + }); } @Override diff --git a/app/src/main/java/com/example/quiz/BetValidation.java b/app/src/main/java/com/example/quiz/BetValidation.java index 1b00d98..985998b 100644 --- a/app/src/main/java/com/example/quiz/BetValidation.java +++ b/app/src/main/java/com/example/quiz/BetValidation.java @@ -45,6 +45,7 @@ import com.example.quiz.data.model.enums.PariStatut; import com.example.quiz.databinding.FragmentBetValidationBinding; import com.example.quiz.utils.BluetoothUtils; import com.example.quiz.utils.Result; +import com.example.quiz.utils.SharedPrefsHelper; import com.example.quiz.viewModel.PariViewModel; import com.example.quiz.viewModel.SharedViewModel; import com.google.android.material.appbar.MaterialToolbar; @@ -77,20 +78,24 @@ public class BetValidation extends Fragment { private AlertDialog dialog; + private int nombreX; + private boolean order; + private long mise; + private TypeOfBet typeOfBet; + SharedPrefsHelper prefsHelper; + private Reunion reunion; private Course course; private int coeff; - private int mise; - private ActivityResultLauncher enableBluetoothLauncher; @@ -114,6 +119,7 @@ public class BetValidation extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + prefsHelper = SharedPrefsHelper.getInstance(getContext()); } @Override @@ -139,8 +145,8 @@ public class BetValidation extends Fragment { return; } coeff = Integer.parseInt(charSequence.toString()); - calculateMise(selectedHorses.getValue().size()); - binding.mise.setText(String.valueOf(mise+" CFA")); + calculateMise(selectedHorses.getValue()); + } @Override @@ -180,7 +186,15 @@ public class BetValidation extends Fragment { textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); textView.setOnClickListener(v -> { final List horses = new ArrayList<>(selectedHorses.getValue()); - if (horses.contains(horse)) { + if(horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse() && horse.equals("X")){ + Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show(); + return; + } + if(_notClickable(horses) && horse.equals("X")){ + Toast.makeText(getContext(), "Vous ne pouvez plus sélectionner X", Toast.LENGTH_SHORT).show(); + return; + } + if (horses.contains(horse) && !horse.equals("X")) { horses.remove(horse); selectedHorses.setValue(horses); v.setSelected(false); @@ -196,15 +210,27 @@ public class BetValidation extends Fragment { .collect(Collectors.joining("-")); binding.combination.setText( combinationText); }); - - return textView; } + + boolean _notClickable(List selectedHorses){ + int numberOfElement = 0; + if(shared.typeOfBet.getValue().getNumberOfHorse() < 2){ + return true; + } + for(String horse: selectedHorses){ + numberOfElement = horse.equals("X")?numberOfElement+1:numberOfElement; + } + nombreX = numberOfElement; + return numberOfElement == shared.typeOfBet.getValue().getNumberOfHorse() - 1; + } + @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); shared = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); + setSelectedTypeOfBetImage(); pariViewModel = new ViewModelProvider(this).get(PariViewModel.class); typeOfBet = shared.typeOfBet.getValue(); reunion = shared.selectedReunion.getValue(); @@ -241,8 +267,12 @@ public class BetValidation extends Fragment { selectedHorses.observe(getViewLifecycleOwner(), new Observer>() { @Override public void onChanged(List horses) { - calculateMise(horses.size()); - binding.mise.setText(String.valueOf(mise+" CFA")); + calculateMise(horses); + if(horses.size() > shared.typeOfBet.getValue().getNumberOfHorse()){ + binding.elargie.setVisibility(View.VISIBLE); + }else{ + binding.elargie.setVisibility(View.GONE); + } if(shared.typeOfBet.getValue().getNumberOfHorse() > 2 && horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse()){ binding.order.setVisibility(View.VISIBLE); }else{ @@ -252,8 +282,7 @@ public class BetValidation extends Fragment { }); binding.order.setOnCheckedChangeListener((buttonView, isChecked) -> { order = isChecked; - calculateMise(selectedHorses.getValue().size()); - binding.mise.setText(String.valueOf(mise+" CFA")); + calculateMise(selectedHorses.getValue()); }); binding.betValidateBtn.setOnClickListener(v->{ @@ -274,10 +303,10 @@ public class BetValidation extends Fragment { } + Pari pari = new Pari( generate12Digits(), shared.typeOfBet.getValue().getName(), - "GAGNANT", mise, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").format(LocalDateTime.now()), true, @@ -285,25 +314,11 @@ public class BetValidation extends Fragment { new PariCourseDto(shared.selectedCourse.getValue().getId()), selectedHorses.getValue(), order?new ArrayList(): selectedHorses.getValue(), - order, - "MULTI_4" + !order, + "MULTI_4", + prefsHelper.get("code") ); - pariViewModel.createPari(pari).observe(getViewLifecycleOwner(),new Observer>() { - @Override - public void onChanged(Result pariResult) { - switch (pariResult.status){ - case ERROR: - Toast.makeText(getContext(), pariResult.message, Toast.LENGTH_SHORT).show(); - break; - case LOADING: - Toast.makeText(getContext(), "En cours", Toast.LENGTH_SHORT).show(); - break; - case SUCCESS: - _showPariDialog(pariResult.data); - break; - } - } - }); + _showPariDialog(pari); }); binding.backBtn.setOnClickListener(v->{ @@ -315,6 +330,26 @@ public class BetValidation extends Fragment { }); } + private void setSelectedTypeOfBetImage(){ + switch (shared.typeOfBet.getValue().getName()){ + case "COUPLE_PLACE": + binding.icTypeOfBet.setImageResource(R.drawable.ic_couple_place); + break; + case "COUPLE_GAGNANT": + binding.icTypeOfBet.setImageResource(R.drawable.ic_couple_gagnant); + break; + case "TIERCE": + binding.icTypeOfBet.setImageResource(R.drawable.ic_tierce); + break; + case "QUARTE": + binding.icTypeOfBet.setImageResource(R.drawable.ic_quarte); + break; + case "QUINTE": + binding.icTypeOfBet.setImageResource(R.drawable.ic_quinte_plus); + break; + } + } + public void printPari(Pari pari) throws WriterException { Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); @@ -332,15 +367,16 @@ public class BetValidation extends Fragment { tspl.append("--------------------------------\n"); boolean isElargie = selectedHorses.getValue().size()>shared.typeOfBet.getValue().getNumberOfHorse(); tspl.append(isElargie?pari.getTypePari()+"/Elargie":pari.getTypePari()).append("\n"); + tspl.append(order?"COMBINAISON COMPLETE"+"\n":""); String combinationText = selectedHorses.getValue().stream() .map(String::valueOf) .collect(Collectors.joining("-")); tspl.append(combinationText).append("\n"); tspl.append("COEF: "+String.valueOf(coeff)).append(".0").append("\n"); tspl.append("--------------------------------\n"); - tspl.append("MONTANT: ").append(mise).append(" XOF\n"); + tspl.append("MONTANT: ").append(pari.getMise()).append(" XOF\n"); tspl.append("-------------------------------\n"); - tspl.append("AGENT: ").append(" 3332\n"); + tspl.append("AGENT: ").append(prefsHelper.get("code")).append("\n"); tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n"); if (BluetoothUtils.needsBluetoothPermissions()) { if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { @@ -378,7 +414,7 @@ public class BetValidation extends Fragment { TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff); aler_coeff.setText("Coef:"+String.valueOf(coeff)); TextView alert_montant = (TextView) view.findViewById(R.id.alert_montant); - alert_montant.setText("Montant: "+String.valueOf(mise)+" CFA"); + alert_montant.setText("Montant: "+String.valueOf(pari.getMise())+" CFA"); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder.setView(view); builder.setCancelable(false); @@ -387,22 +423,35 @@ public class BetValidation extends Fragment { dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); view.findViewById(R.id.alert_validate).setOnClickListener(v->{ - try { - printPari(pari); - dialog.dismiss(); - } catch (WriterException e) { - throw new RuntimeException(e); - } + pariViewModel.createPari(pari).observe(getViewLifecycleOwner(),new Observer>() { + @Override + public void onChanged(Result pariResult) { + switch (pariResult.status){ + case ERROR: + Toast.makeText(getContext(), pariResult.message, Toast.LENGTH_SHORT).show(); + break; + case LOADING: + Toast.makeText(getContext(), "En cours", Toast.LENGTH_SHORT).show(); + break; + case SUCCESS: + try { + printPari(pari); + dialog.dismiss(); + } catch (WriterException e) { + throw new RuntimeException(e); + } + break; + } + } + }); }); view.findViewById(R.id.alert_cancel).setOnClickListener(v -> { dialog.dismiss(); }); - + dialog.show(); } void _initializeToZero(){ - mise = 0; - binding.mise.setText(String.valueOf(mise+" CFA")); selectedHorses.setValue(List.of()); binding.combination.setText(""); binding.order.setChecked(false); @@ -413,56 +462,67 @@ public class BetValidation extends Fragment { setupNumberGrid(binding.gridNumbers); } - public void calculateMise(int nombreChevauxSelectionnes){ - if(typeOfBet.getNumberOfHorse() == 1){ - if(nombreChevauxSelectionnes==1){ + public void calculateMise(List selectedHorses){ + _notClickable(selectedHorses); + int nombreChevauxSelectionnes = selectedHorses.size(); + long mise = 0; + if(shared.typeOfBet.getValue() == null || shared.selectedCourse.getValue() == null){ + return; + } + int typeOfBetHorses = shared.typeOfBet.getValue().getNumberOfHorse(); + int partants = shared.selectedCourse.getValue().getPartants(); + if(shared.typeOfBet.getValue().getNumberOfHorse() > nombreChevauxSelectionnes){ + binding.mise.setText(mise+" CFA"); + return; + } + if(typeOfBetHorses == 2){ + mise = 500; + }else{ + if(typeOfBetHorses == 5){ mise = 300; + }else{ + mise = 200; } } - if(typeOfBet.getNumberOfHorse() == 2){ - if(nombreChevauxSelectionnes == 2){ - mise = 400; + mise = mise * coeff; + if(nombreX>0){ + if(nombreChevauxSelectionnes == typeOfBetHorses){ + mise = mise * _calculateArrangement((partants - (typeOfBetHorses-nombreX)), nombreX); + }else{ + mise = mise * _calculateArrangement(nombreChevauxSelectionnes - typeOfBetHorses , nombreX); } - if(nombreChevauxSelectionnes > 2){ - mise = 400 + (nombreChevauxSelectionnes - 2)*300; + if(order){ + mise = mise * _calculateArrangement(typeOfBetHorses, (typeOfBetHorses-nombreX)); } + this.mise = mise; + binding.mise.setText(mise+" CFA"); + return; } - if(typeOfBet.getNumberOfHorse() == 3){ - if(nombreChevauxSelectionnes == 3){ - mise = 500; - } - if(nombreChevauxSelectionnes > 3){ - mise = 500 + (nombreChevauxSelectionnes - 3)*500; - } + mise = mise * _calculateCombinaison(nombreChevauxSelectionnes, typeOfBetHorses); + if(order){ + mise = mise * _calculateArrangement(nombreChevauxSelectionnes, typeOfBetHorses); } - if(typeOfBet.getNumberOfHorse() == 4){ - if(nombreChevauxSelectionnes == 4){ - mise = 600; - } - if(nombreChevauxSelectionnes > 4){ - mise = 600 + (nombreChevauxSelectionnes - 4)*600; - } - } - if(typeOfBet.getNumberOfHorse() == 5){ - if(nombreChevauxSelectionnes == 5){ - mise = 1200; - } - if(nombreChevauxSelectionnes > 5){ - mise = 1200 + (nombreChevauxSelectionnes - 5)*1200; - } - } - mise = order?mise * coeff * _calculateFactorial(shared.typeOfBet.getValue().getNumberOfHorse()):mise * coeff; + this.mise = mise; + binding.mise.setText(mise+" CFA"); } - Integer _calculateFactorial(int n){ - int f = 1; + Long _calculateArrangement(int n, int k){ + return _calculateFactorial(n) / _calculateFactorial(n-k); + } + + Long _calculateCombinaison(int n, int k){ + return _calculateFactorial(n) / (_calculateFactorial(k) * _calculateFactorial(n - k)); + } + + Long _calculateFactorial(int n){ + long f = 1; if(n == 0){ - return f; + return f; } for(int i = 1; i <=n; i++){ f *= i; } - return f; + return f; } diff --git a/app/src/main/java/com/example/quiz/Caisse.java b/app/src/main/java/com/example/quiz/Caisse.java index e6da450..9ba77fc 100644 --- a/app/src/main/java/com/example/quiz/Caisse.java +++ b/app/src/main/java/com/example/quiz/Caisse.java @@ -78,6 +78,14 @@ public class Caisse extends Fragment { .addToBackStack(null) .commit(); }); + + binding.lastBetsBtn.setOnClickListener(v -> { + getActivity().getSupportFragmentManager() + .beginTransaction() + .replace(R.id.nav_host_fragment_content_main, DerniersParis.newInstance()) + .addToBackStack(null) + .commit(); + }); } @Override diff --git a/app/src/main/java/com/example/quiz/DerniersParis.java b/app/src/main/java/com/example/quiz/DerniersParis.java new file mode 100644 index 0000000..98c5ea6 --- /dev/null +++ b/app/src/main/java/com/example/quiz/DerniersParis.java @@ -0,0 +1,105 @@ +package com.example.quiz; + +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import com.example.quiz.data.adapter.LastBetsAdapter; +import com.example.quiz.data.model.Pari; +import com.example.quiz.databinding.FragmentDerniersParisBinding; +import com.example.quiz.utils.Result; +import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.viewModel.PariViewModel; +import com.google.android.material.appbar.MaterialToolbar; + +import java.util.List; + +import dagger.hilt.android.AndroidEntryPoint; + +/** + * A simple {@link Fragment} subclass. + * Use the {@link DerniersParis#newInstance} factory method to + * create an instance of this fragment. + */ + +@AndroidEntryPoint +public class DerniersParis extends Fragment { + + FragmentDerniersParisBinding binding; + SharedPrefsHelper prefsHelper; + PariViewModel viewModel; + + LastBetsAdapter adapter; + + public DerniersParis() { + // Required empty public constructor + } + + // TODO: Rename and change types and number of parameters + public static DerniersParis newInstance() { + DerniersParis fragment = new DerniersParis(); + Bundle args = new Bundle(); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + prefsHelper = SharedPrefsHelper.getInstance(getContext()); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + binding = FragmentDerniersParisBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + binding.lastBetsRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); + viewModel = new ViewModelProvider(this).get(PariViewModel.class); + viewModel.getDerniersParis(prefsHelper.get("code")).observe(getViewLifecycleOwner(), new Observer>>() { + @Override + public void onChanged(Result> listResult) { + switch (listResult.status){ + case LOADING: + Toast.makeText(getContext(), "En cours", Toast.LENGTH_SHORT).show(); + break; + case ERROR: + Toast.makeText(getContext(), listResult.message, Toast.LENGTH_SHORT).show(); + break; + case SUCCESS: + adapter = new LastBetsAdapter(listResult.data, pari -> { + }); + binding.lastBetsRecyclerView.setAdapter(adapter); + } + } + }); + } + + @Override + public void onResume() { + super.onResume(); + AppCompatActivity activity = (AppCompatActivity) getActivity(); + if(activity!=null){ + MaterialToolbar toolbar = activity.findViewById(R.id.toolbar); + activity.setSupportActionBar(toolbar); + toolbar.setTitle("Derniers Paris"); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/quiz/ListOfTypeOfBets.java b/app/src/main/java/com/example/quiz/ListOfTypeOfBets.java index 74461cd..2d4209d 100644 --- a/app/src/main/java/com/example/quiz/ListOfTypeOfBets.java +++ b/app/src/main/java/com/example/quiz/ListOfTypeOfBets.java @@ -92,17 +92,17 @@ public class ListOfTypeOfBets extends Fragment { ), new TypeOfBet( "Tierce", - "TRIPLET", + "TIERCE", 3 ), new TypeOfBet( "Quarte +", - "QUARTE_PLUS", + "QUARTE", 4 ), new TypeOfBet( "Quinte +", - "QUINTE_PLUS", + "QUINTE", 5 ) ); @@ -129,7 +129,7 @@ public class ListOfTypeOfBets extends Fragment { }); Button btnValidate = binding.btnValidate; btnValidate.setOnClickListener(v->{ - if(shared.typeOfBet == null){ + if(shared.typeOfBet.getValue() == null){ Toast.makeText(getContext(),"Aucun Type de jeu choisi", Toast.LENGTH_SHORT).show(); return; } diff --git a/app/src/main/java/com/example/quiz/PageQuiz.java b/app/src/main/java/com/example/quiz/PageQuiz.java index a7f444b..c23a956 100644 --- a/app/src/main/java/com/example/quiz/PageQuiz.java +++ b/app/src/main/java/com/example/quiz/PageQuiz.java @@ -135,10 +135,12 @@ public class PageQuiz extends AppCompatActivity { private void loginSuccess(LoginResponse loginResponse){ + prefsHelper.save("id", String.valueOf(loginResponse.getId())); prefsHelper.save("firstName", loginResponse.getPrenom()); prefsHelper.save("lastName", loginResponse.getNom()); prefsHelper.save("profile", loginResponse.getProfile()); prefsHelper.save("limit", String.valueOf(loginResponse.getLimiteSuperieure())); + prefsHelper.save("code", loginResponse.getCode()); } @Override diff --git a/app/src/main/java/com/example/quiz/ScannerDialog.java b/app/src/main/java/com/example/quiz/ScannerDialog.java new file mode 100644 index 0000000..5efcc83 --- /dev/null +++ b/app/src/main/java/com/example/quiz/ScannerDialog.java @@ -0,0 +1,137 @@ +package com.example.quiz; + +import android.annotation.SuppressLint; +import android.content.pm.PackageManager; +import android.media.Image; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.Manifest; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ImageAnalysis; +import androidx.camera.core.Preview; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.DialogFragment; + +import com.example.quiz.databinding.FragmentScanBinding; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.mlkit.vision.barcode.BarcodeScanner; +import com.google.mlkit.vision.barcode.BarcodeScanning; +import com.google.mlkit.vision.barcode.common.Barcode; +import com.google.mlkit.vision.common.InputImage; + + + +public class ScannerDialog extends DialogFragment { + private PreviewView previewView; + private ProcessCameraProvider cameraProvider; + + public interface OnBarcodeScannedListener { + void onBarcodeScanned(String code); + } + + private OnBarcodeScannedListener listener; + + private FragmentScanBinding binding; + + public void setOnBarcodeScannedListener(OnBarcodeScannedListener listener){ + this.listener = listener; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + binding = FragmentScanBinding.inflate(inflater, container, false); + return binding.getRoot(); + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + previewView = view.findViewById(R.id.cameraPreview); + + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + requestPermissions(new String[]{Manifest.permission.CAMERA}, 1001); + } else { + startCamera(); + } + + view.findViewById(R.id.closeScanDialog).setOnClickListener(v -> dismiss()); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == 1001 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + startCamera(); + } else { + Toast.makeText(getContext(), "Permission caméra refusée", Toast.LENGTH_SHORT).show(); + dismiss(); + } + } + + private void startCamera() { + final ListenableFuture cameraProviderFuture = + ProcessCameraProvider.getInstance(getContext()); + + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + bindPreviewAndScanner(); + } catch (Exception e) { + e.printStackTrace(); + } + }, ContextCompat.getMainExecutor(getContext())); + } + + private void bindPreviewAndScanner() { + cameraProvider.unbindAll(); + + Preview preview = new Preview.Builder().build(); + CameraSelector selector = CameraSelector.DEFAULT_BACK_CAMERA; + preview.setSurfaceProvider(previewView.getSurfaceProvider()); + + ImageAnalysis analysis = new ImageAnalysis.Builder() + .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) + .build(); + + analysis.setAnalyzer(ContextCompat.getMainExecutor(getContext()), imageProxy -> { + @SuppressLint("UnsafeOptInUsageError") + Image mediaImage = imageProxy.getImage(); + if (mediaImage != null) { + InputImage inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.getImageInfo().getRotationDegrees()); + + BarcodeScanner scanner = BarcodeScanning.getClient(); + + scanner.process(inputImage) + .addOnSuccessListener(barcodes -> { + for (Barcode b : barcodes) { + String value = b.getRawValue(); + if (value != null && listener != null) { + listener.onBarcodeScanned(value); + dismiss(); // Fermer le dialog après scan + scanner.close(); + imageProxy.close(); + cameraProvider.unbindAll(); + return; + } + } + }) + .addOnFailureListener(Throwable::printStackTrace) + .addOnCompleteListener(task -> imageProxy.close()); + } + }); + + cameraProvider.bindToLifecycle(this, selector, preview, analysis); + } +} diff --git a/app/src/main/java/com/example/quiz/Sold.java b/app/src/main/java/com/example/quiz/Sold.java index 18b4bb3..49eb1d8 100644 --- a/app/src/main/java/com/example/quiz/Sold.java +++ b/app/src/main/java/com/example/quiz/Sold.java @@ -9,26 +9,39 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import com.example.quiz.databinding.FragmentSoldBinding; +import com.example.quiz.utils.Result; +import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.viewModel.PariViewModel; import com.google.android.material.appbar.MaterialToolbar; import java.util.Calendar; +import dagger.hilt.android.AndroidEntryPoint; + /** * A simple {@link Fragment} subclass. * Use the {@link Sold#newInstance} factory method to * create an instance of this fragment. */ +@AndroidEntryPoint public class Sold extends Fragment { FragmentSoldBinding binding; + PariViewModel pariViewModel; + SharedPrefsHelper prefsHelper; + public Sold() { // Required empty public constructor } @@ -44,6 +57,7 @@ public class Sold extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + prefsHelper = SharedPrefsHelper.getInstance(getContext()); AppCompatActivity activity = (AppCompatActivity) getActivity(); if(activity != null){ MaterialToolbar toolbar = activity.findViewById(R.id.toolbar); @@ -66,6 +80,7 @@ public class Sold extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + pariViewModel = new ViewModelProvider(this).get(PariViewModel.class); binding.btnByCourse.setOnClickListener(v -> { FragmentManager fragmentManager = getParentFragmentManager(); SoldByCourse soldByCourse = SoldByCourse.newInstance(); @@ -86,14 +101,26 @@ public class Sold extends Fragment { DatePickerDialog datePickerDialog = new DatePickerDialog( getContext(), (view, year, month, dayOfMonth) -> { - String date = dayOfMonth + "/" + (month + 1) + "/" + year; - //Toast.makeText(getContext(), date, Toast.LENGTH_SHORT).show(); - new AlertDialog.Builder(getContext()) - .setTitle("Solde") - .setMessage("Solde la course 3000CFA") - .setPositiveButton("Ok", (dialog, which)->{ - dialog.dismiss(); - }).show(); + String date = year + "-" + (month + 1) + "-" + dayOfMonth; + pariViewModel.getSoldeByDay(prefsHelper.get("code"), date).observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(Result doubleResult) { + switch (doubleResult.status){ + case LOADING:{ + Toast.makeText(getContext(), "En cours", Toast.LENGTH_SHORT).show(); + break; + } + case ERROR:{ + Log.d("Response", doubleResult.message); + break; + } + case SUCCESS:{ + _showSold(doubleResult.data); + break; + } + } + } + }); }, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), @@ -102,4 +129,13 @@ public class Sold extends Fragment { datePickerDialog.show(); } + + void _showSold(double solde){ + new AlertDialog.Builder(getContext()) + .setTitle("Solde") + .setMessage("Solde la course "+solde) + .setPositiveButton("Ok", (dialog, which)->{ + dialog.dismiss(); + }).show(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/quiz/SoldByCourse.java b/app/src/main/java/com/example/quiz/SoldByCourse.java index 2e17394..859f5e3 100644 --- a/app/src/main/java/com/example/quiz/SoldByCourse.java +++ b/app/src/main/java/com/example/quiz/SoldByCourse.java @@ -6,26 +6,35 @@ import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; +import androidx.lifecycle.Observer; +import androidx.lifecycle.ViewModelProvider; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Toast; import com.example.quiz.databinding.FragmentSoldByCourseBinding; +import com.example.quiz.utils.Result; +import com.example.quiz.utils.SharedPrefsHelper; +import com.example.quiz.viewModel.PariViewModel; + +import dagger.hilt.android.AndroidEntryPoint; /** * A simple {@link Fragment} subclass. * Use the {@link SoldByCourse#newInstance} factory method to * create an instance of this fragment. */ + +@AndroidEntryPoint public class SoldByCourse extends Fragment { FragmentSoldByCourseBinding binding; - // TODO: Rename parameter arguments, choose names that match - // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER - private static final String ARG_PARAM1 = "param1"; - private static final String ARG_PARAM2 = "param2"; + PariViewModel pariViewModel; + + SharedPrefsHelper prefsHelper; public static SoldByCourse newInstance() { @@ -39,6 +48,7 @@ public class SoldByCourse extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + prefsHelper = SharedPrefsHelper.getInstance(getContext()); } @Override @@ -52,19 +62,43 @@ public class SoldByCourse extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + pariViewModel = new ViewModelProvider(this).get(PariViewModel.class); + binding.btnCheckBalance.setOnClickListener(v -> { if(binding.etRaceNumber.getText().toString().isEmpty()){ binding.etRaceNumber.setError("Veuillez entrer un numéro de course"); return; } - new AlertDialog.Builder(getContext()) - .setTitle("Solde") - .setMessage("Solde la course 3000CFA") - .setPositiveButton("Ok", (dialog, which) -> { - binding.etRaceNumber.setText(""); - dialog.dismiss(); - }) - .show(); + pariViewModel.getSoldeByCourse(prefsHelper.get("code"), binding.etRaceNumber.getText().toString()).observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(Result doubleResult) { + switch (doubleResult.status){ + case LOADING:{ + Toast.makeText(getContext(), "Chargement..", Toast.LENGTH_SHORT).show(); + break; + } + case ERROR:{ + Toast.makeText(getContext(), doubleResult.message, Toast.LENGTH_SHORT).show(); + break; + } + case SUCCESS:{ + _showPariDialog(doubleResult.data); + break; + } + } + } + }); }); } + + void _showPariDialog(double solde){ + new AlertDialog.Builder(getContext()) + .setTitle("Solde") + .setMessage("Solde la course "+solde) + .setPositiveButton("Ok", (dialog, which) -> { + binding.etRaceNumber.setText(""); + dialog.dismiss(); + }) + .show(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/quiz/WinTicket.java b/app/src/main/java/com/example/quiz/WinTicket.java index 6530dcc..7a3aacc 100644 --- a/app/src/main/java/com/example/quiz/WinTicket.java +++ b/app/src/main/java/com/example/quiz/WinTicket.java @@ -51,6 +51,13 @@ public class WinTicket extends Fragment { binding.winTicketBtnBack.setOnClickListener(v -> { getActivity().onBackPressed(); }); + binding.scanTicketBtn.setOnClickListener(v ->{ + ScannerDialog scannerDialog = new ScannerDialog(); + scannerDialog.setOnBarcodeScannedListener(code -> { + binding.referenceTicket.setText(code); + }); + scannerDialog.show(getParentFragmentManager(), "scanner"); + }); } @Override diff --git a/app/src/main/java/com/example/quiz/data/adapter/BetsAdapter.java b/app/src/main/java/com/example/quiz/data/adapter/BetsAdapter.java index 626ae41..8a3c088 100644 --- a/app/src/main/java/com/example/quiz/data/adapter/BetsAdapter.java +++ b/app/src/main/java/com/example/quiz/data/adapter/BetsAdapter.java @@ -14,6 +14,8 @@ import com.example.quiz.data.model.Course; import com.example.quiz.viewModel.SharedViewModel; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; public class BetsAdapter extends RecyclerView.Adapter { @@ -51,7 +53,12 @@ public class BetsAdapter extends RecyclerView.Adapter public void onBindViewHolder(@NonNull BetViewHolder holder, int position) { Course bet = bets.get(position); - holder.tvDate.setText(String.valueOf(bet.getDateDepartCourse())); + holder.tvDate.setText(LocalDateTime.parse( + bet.getDateDepartCourse(), + DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") + ).format( + DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss") + )); holder.tvName.setText(bet.getNom()); if (shared != null && shared.selectedReunion.getValue() != null) { diff --git a/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java b/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java new file mode 100644 index 0000000..e85434b --- /dev/null +++ b/app/src/main/java/com/example/quiz/data/adapter/LastBetsAdapter.java @@ -0,0 +1,120 @@ +package com.example.quiz.data.adapter; + +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; +import com.example.quiz.R; +import com.example.quiz.data.model.Pari; +import java.util.ArrayList; +import java.util.List; + +public class LastBetsAdapter extends RecyclerView.Adapter { + + private List listeParis = new ArrayList<>(); // évite les NPE + private OnBetClick onBetClick; // peut être null si tu veux + + public interface OnBetClick { + void onItemClick(Pari pari); + } + + public LastBetsAdapter(List listeParis, OnBetClick onBetClick) { + if (listeParis != null) this.listeParis = listeParis; + this.onBetClick = onBetClick; + } + + // Constructeur vide utile si tu veux créer puis setData ensuite + public LastBetsAdapter(OnBetClick onBetClick) { + this.onBetClick = onBetClick; + } + + public void setData(List newList) { + if (newList == null) { + this.listeParis = new ArrayList<>(); + } else { + this.listeParis = newList; + } + notifyDataSetChanged(); + } + + public void addItem(Pari pari) { + if (pari == null) return; + this.listeParis.add(pari); + notifyItemInserted(listeParis.size() - 1); + } + + public void clear() { + this.listeParis.clear(); + notifyDataSetChanged(); + } + + @NonNull + @Override + public LastBetsViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.last_bets_item, parent, false); + return new LastBetsViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull LastBetsViewHolder holder, int position) { + Pari pari = listeParis.get(position); + if (pari == null) return; + + holder.typeOfCourse.setText(pari.getCourse().getType()); + holder.refenceTicket.setText(pari.getNumeroTicket()); + + // Type (défensif : vérifie null) + holder.betType.setText(pari.getTypePari() != null ? pari.getTypePari() : "-"); + + // Course (défensif : course peut être null) + if (pari.getCourse() != null) { + holder.course.setText("Course: " + pari.getCourse().getId()); + } else { + holder.course.setText("Course: -"); + } + + // Chevaux : join en toute sécurité (gère Integer list ou String list) + List chevaux = pari.getChevauxSelectionnes(); + if (chevaux != null && !chevaux.isEmpty()) { + // convertir en strings + List str = new ArrayList<>(chevaux.size()); + for (Object o : chevaux) { + str.add(String.valueOf(o)); + } + // TextUtils.join est compatible avec tous les niveaux API + holder.horses.setText("Chevaux : " + TextUtils.join("-", str)); + } else { + holder.horses.setText("Chevaux : -"); + } + + // Mise (défensif) + holder.mise.setText("Mise: " + pari.getMise() + " CFA"); + + // click listener défensif + holder.itemView.setOnClickListener(v -> { + if (onBetClick != null) onBetClick.onItemClick(pari); + }); + } + + @Override + public int getItemCount() { + return (listeParis != null) ? listeParis.size() : 0; + } + + public static class LastBetsViewHolder extends RecyclerView.ViewHolder { + TextView betType, horses, course, mise, refenceTicket, typeOfCourse; + + public LastBetsViewHolder(@NonNull View itemView) { + super(itemView); + betType = itemView.findViewById(R.id.last_bet_type); + course = itemView.findViewById(R.id.last_bet_course); + horses = itemView.findViewById(R.id.last_bet_horses); + mise = itemView.findViewById(R.id.last_bet_mise); + refenceTicket = itemView.findViewById(R.id.reference_ticket); + typeOfCourse = itemView.findViewById(R.id.type_of_course); + } + } +} diff --git a/app/src/main/java/com/example/quiz/data/model/Pari.java b/app/src/main/java/com/example/quiz/data/model/Pari.java index e191aa9..f50ef19 100644 --- a/app/src/main/java/com/example/quiz/data/model/Pari.java +++ b/app/src/main/java/com/example/quiz/data/model/Pari.java @@ -7,7 +7,6 @@ import java.util.Map; public class Pari { private String numeroTicket; private String typePari; - private String typeFormule; private double mise; private String datePari; private boolean estPaye; @@ -18,10 +17,11 @@ public class Pari { private boolean validationOrdreExact; private String typeMulti; - public Pari(String numeroTicket, String typePari, String typeFormule, double mise, String datePari, boolean estPaye, boolean estRembourse, PariCourseDto course, List chevauxSelectionnes, List ordrePredit, boolean validationOrdreExact, String typeMulti) { + private String createdBy; + + public Pari(String numeroTicket, String typePari, double mise, String datePari, boolean estPaye, boolean estRembourse, PariCourseDto course, List chevauxSelectionnes, List ordrePredit, boolean validationOrdreExact, String typeMulti, String createdBy) { this.numeroTicket = numeroTicket; this.typePari = typePari; - this.typeFormule = typeFormule; this.mise = mise; this.datePari = datePari; this.estPaye = estPaye; @@ -31,6 +31,7 @@ public class Pari { this.ordrePredit = ordrePredit; this.validationOrdreExact = validationOrdreExact; this.typeMulti = typeMulti; + this.createdBy = createdBy; } public String getNumeroTicket() { @@ -49,14 +50,6 @@ public class Pari { this.typePari = typePari; } - public String getTypeFormule() { - return typeFormule; - } - - public void setTypeFormule(String typeFormule) { - this.typeFormule = typeFormule; - } - public double getMise() { return mise; } @@ -128,4 +121,12 @@ public class Pari { public void setTypeMulti(String typeMulti) { this.typeMulti = typeMulti; } + + public String getCreatedBy() { + return createdBy; + } + + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } } diff --git a/app/src/main/java/com/example/quiz/data/model/dtos/PariCourseDto.java b/app/src/main/java/com/example/quiz/data/model/dtos/PariCourseDto.java index 8086a9e..79cc03b 100644 --- a/app/src/main/java/com/example/quiz/data/model/dtos/PariCourseDto.java +++ b/app/src/main/java/com/example/quiz/data/model/dtos/PariCourseDto.java @@ -3,10 +3,43 @@ package com.example.quiz.data.model.dtos; public class PariCourseDto { private int id; + private String nom; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + private String type; + + + public PariCourseDto(int id) { this.id = id; } + public PariCourseDto(String nom) { + this.nom = nom; + } + + + public PariCourseDto(int id, String nom, String type) { + this.id = id; + this.nom = nom; + this.type = type; + } + + public String getNom() { + return nom; + } + + public void setNom(String nom) { + this.nom = nom; + } + public int getId() { return id; } diff --git a/app/src/main/java/com/example/quiz/data/remote/ApiClient.java b/app/src/main/java/com/example/quiz/data/remote/ApiClient.java index 32df308..aa89401 100644 --- a/app/src/main/java/com/example/quiz/data/remote/ApiClient.java +++ b/app/src/main/java/com/example/quiz/data/remote/ApiClient.java @@ -20,7 +20,7 @@ import retrofit2.converter.gson.GsonConverterFactory; @Module @InstallIn(SingletonComponent.class) public class ApiClient { - private static final String BASE_URL = "https://970b6b1c025c.ngrok-free.app/api/v1/"; + private static final String BASE_URL = "https://boxer-adapting-bluegill.ngrok-free.app/api/v1/"; @Provides @Singleton diff --git a/app/src/main/java/com/example/quiz/data/remote/ApiService.java b/app/src/main/java/com/example/quiz/data/remote/ApiService.java index 588a813..2752a2a 100644 --- a/app/src/main/java/com/example/quiz/data/remote/ApiService.java +++ b/app/src/main/java/com/example/quiz/data/remote/ApiService.java @@ -12,7 +12,9 @@ import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.GET; import retrofit2.http.POST; +import retrofit2.http.PUT; import retrofit2.http.Path; +import retrofit2.http.Query; public interface ApiService { @GET("reunions") @@ -26,4 +28,17 @@ public interface ApiService { @POST("auth/agent/login") Call login(@Body LoginPayload loginPayload); + + @GET("pari/created-by/{created-by}/today") + Call> derniersParis(@Path("created-by") String createdBy); + + @PUT("pari/annuler/{numeroTicket}") + Call annulerPari(@Path("numeroTicket") String numeroTicket); + + @GET("pari/solde/{createdBy}/course/{courseId}") + Call getSoldeByCourse(@Path("createdBy") String createdBy, @Path("courseId") String courseId); + + @GET("pari/solde/{createdBy}") + Call getSoldeByDay(@Path("createdBy") String createdBy, @Query("date") String day); + } diff --git a/app/src/main/java/com/example/quiz/data/repository/PariRepository.java b/app/src/main/java/com/example/quiz/data/repository/PariRepository.java index 41763eb..9f1fa4b 100644 --- a/app/src/main/java/com/example/quiz/data/repository/PariRepository.java +++ b/app/src/main/java/com/example/quiz/data/repository/PariRepository.java @@ -10,6 +10,8 @@ import com.example.quiz.data.model.Pari; import com.example.quiz.data.remote.ApiService; import com.example.quiz.utils.Result; +import java.util.List; + import javax.inject.Inject; import retrofit2.Call; @@ -57,5 +59,111 @@ public class PariRepository { return pariResponse; } + public LiveData>> derniersParis(String createdBy){ + MutableLiveData>> derniersParis = new MutableLiveData<>(); + derniersParis.setValue(Result.loading()); + apiService.derniersParis(createdBy).enqueue(new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if(response.isSuccessful() && response.body() != null){ + derniersParis.postValue(Result.success(response.body())); + }else{ + try{ + String errorBody = response.errorBody() != null ? + response.errorBody().string() : "Erreur inconnue"; + + derniersParis.postValue(Result.error(errorBody)); + }catch (Exception e){ + derniersParis.postValue(Result.error(e.getMessage())); + } + } + } + + @Override + public void onFailure(Call> call, Throwable throwable) { + derniersParis.postValue(Result.error(throwable.getMessage())); + } + }); + + return derniersParis; + } + + public LiveData> annulerPari(String numeroTicket){ + MutableLiveData> pariResponse = new MutableLiveData<>(); + pariResponse.setValue(Result.loading()); + apiService.annulerPari(numeroTicket).enqueue(new Callback(){ + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful()){ + pariResponse.postValue(Result.success(response.body())); + }else{ + try{ + String errorBody = response.errorBody() != null ? + response.errorBody().string() : "Erreur inconnue"; + + pariResponse.postValue(Result.error(errorBody)); + }catch (Exception e){ + pariResponse.postValue(Result.error(e.getMessage())); + } + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + pariResponse.postValue(Result.error(throwable.getMessage())); + } + }); + return pariResponse; + } + + public LiveData> getSoldeByCourse(String createdBy, String courseId){ + MutableLiveData> solde = new MutableLiveData<>(); + solde.setValue(Result.loading()); + apiService.getSoldeByCourse(createdBy, courseId).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful()){ + solde.postValue(Result.success(response.body())); + }else{ + try{ + solde.postValue(Result.error(response.errorBody().string())); + }catch (Exception e){ + solde.postValue(Result.error(e.getMessage())); + } + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + solde.postValue(Result.error(throwable.getMessage())); + } + }); + return solde; + } + + public LiveData> getSoldeByDay(String createdBy, String day){ + MutableLiveData> solde = new MutableLiveData<>(); + solde.setValue(Result.loading()); + apiService.getSoldeByDay(createdBy, day).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful()){ + solde.postValue(Result.success(response.body())); + }else{ + try { + solde.postValue(Result.error(response.errorBody().string())); + }catch (Exception e){ + solde.postValue(Result.error(e.getMessage())); + } + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + solde.postValue(Result.error(throwable.getMessage())); + } + }); + return solde; + } } diff --git a/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java b/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java index 05902f7..e87163d 100644 --- a/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java +++ b/app/src/main/java/com/example/quiz/viewModel/PariViewModel.java @@ -7,6 +7,8 @@ import com.example.quiz.data.model.Pari; import com.example.quiz.data.repository.PariRepository; import com.example.quiz.utils.Result; +import java.util.List; + import javax.inject.Inject; import dagger.hilt.android.lifecycle.HiltViewModel; @@ -16,6 +18,14 @@ public class PariViewModel extends ViewModel { private final PariRepository pariRepository; private LiveData> pari; + private LiveData>> derniersParis; + + private LiveData> pariAnnule; + + private LiveData> solde; + + private LiveData> soldeByDay; + @Inject public PariViewModel(PariRepository repository){ this.pariRepository = repository; @@ -27,4 +37,32 @@ public class PariViewModel extends ViewModel { } return this.pari; } + + public LiveData>> getDerniersParis(String createdBy){ + if(derniersParis == null){ + derniersParis = pariRepository.derniersParis(createdBy); + } + return pariRepository.derniersParis(createdBy); + } + + public LiveData> annulerPari(String numeroTicket){ + if(pariAnnule == null){ + pariAnnule = pariRepository.annulerPari(numeroTicket); + } + return pariAnnule; + } + + public LiveData> getSoldeByCourse(String createdBy, String courseId){ + if(solde == null){ + solde = pariRepository.getSoldeByCourse(createdBy, courseId); + } + return solde; + } + + public LiveData> getSoldeByDay(String createdBy, String day){ + if(soldeByDay == null){ + soldeByDay = pariRepository.getSoldeByDay(createdBy, day); + } + return soldeByDay; + } } diff --git a/app/src/main/res/drawable/ic_couple_gagnant.xml b/app/src/main/res/drawable/ic_couple_gagnant.xml new file mode 100644 index 0000000..54be57e --- /dev/null +++ b/app/src/main/res/drawable/ic_couple_gagnant.xml @@ -0,0 +1,540 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_couple_place.xml b/app/src/main/res/drawable/ic_couple_place.xml new file mode 100644 index 0000000..b65258f --- /dev/null +++ b/app/src/main/res/drawable/ic_couple_place.xml @@ -0,0 +1,657 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_quarte.xml b/app/src/main/res/drawable/ic_quarte.xml new file mode 100644 index 0000000..5d6a987 --- /dev/null +++ b/app/src/main/res/drawable/ic_quarte.xml @@ -0,0 +1,435 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_quinte_plus.xml b/app/src/main/res/drawable/ic_quinte_plus.xml new file mode 100644 index 0000000..fa8b2d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_quinte_plus.xml @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_tierce.xml b/app/src/main/res/drawable/ic_tierce.xml new file mode 100644 index 0000000..37bc562 --- /dev/null +++ b/app/src/main/res/drawable/ic_tierce.xml @@ -0,0 +1,297 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_annulation_ticket.xml b/app/src/main/res/layout/fragment_annulation_ticket.xml index 4c0efe9..d6ff4c3 100644 --- a/app/src/main/res/layout/fragment_annulation_ticket.xml +++ b/app/src/main/res/layout/fragment_annulation_ticket.xml @@ -21,6 +21,7 @@ android:textColor="@color/primary_green"> - + android:layout_height="match_parent" + android:background="@color/login_background" + android:id="@+id/login_container" + tools:context=".BetValidation"> - + - - - - - - - - - - - - - - + android:layout_height="match_parent" + android:background="@color/gray" + android:paddingHorizontal="5dp" + android:layout_above="@+id/bottom_buttons"> - - + android:paddingBottom="30dp"> + android:layout_marginTop="5dp" + android:layout_marginBottom="5dp" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + + + + + + + + android:padding="12dp" + android:orientation="horizontal" + android:gravity="center_vertical" + android:background="@android:color/white" + android:elevation="4dp" + android:layout_marginBottom="14dp"> - + android:layout_weight="1" + android:orientation="vertical"> + + + - + + - - + + - - + - + android:orientation="vertical"> - + + + + + + + + + + +