70% of features done!

This commit is contained in:
OnlyPapy98
2025-12-12 17:55:12 +01:00
parent dc93d1320f
commit b3d94ad038
31 changed files with 3334 additions and 285 deletions

View File

@@ -43,6 +43,11 @@ android {
dependencies { dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar")))) implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar", "*.aar"))))
implementation(libs.swiperefreshlayout) 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.retrofit)
implementation(libs.okhttp) implementation(libs.okhttp)
implementation(libs.logging.interceptor) implementation(libs.logging.interceptor)

View File

@@ -6,6 +6,9 @@
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- ✅ Required for Android 12+ --> <!-- ✅ Required for Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" <uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" /> android:usesPermissionFlags="neverForLocation" />
@@ -62,6 +65,7 @@
android:name="com.google.android.geo.API_KEY" android:name="com.google.android.geo.API_KEY"
android:value="YOUR_API_KEY" /> android:value="YOUR_API_KEY" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
android:exported="true" android:exported="true"

View File

@@ -4,22 +4,34 @@ import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import com.example.quiz.data.model.Pari;
import com.example.quiz.databinding.FragmentAnnulationTicketBinding; import com.example.quiz.databinding.FragmentAnnulationTicketBinding;
import com.example.quiz.utils.Result;
import com.example.quiz.viewModel.PariViewModel;
import dagger.hilt.android.AndroidEntryPoint;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Use the {@link AnnulationTicket#newInstance} factory method to * Use the {@link AnnulationTicket#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
@AndroidEntryPoint
public class AnnulationTicket extends Fragment { public class AnnulationTicket extends Fragment {
FragmentAnnulationTicketBinding binding; FragmentAnnulationTicketBinding binding;
PariViewModel viewModel;
public AnnulationTicket() { public AnnulationTicket() {
// Required empty public constructor // Required empty public constructor
} }
@@ -47,10 +59,45 @@ public class AnnulationTicket extends Fragment {
@Override @Override
public void onViewCreated(View view, Bundle savedInstanceState) { public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
viewModel = new ViewModelProvider(this).get(PariViewModel.class);
binding.annuleTicketBtnBack.setOnClickListener(v->{ binding.annuleTicketBtnBack.setOnClickListener(v->{
getActivity().onBackPressed(); 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<Result<Pari>>() {
@Override
public void onChanged(Result<Pari> 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 @Override

View File

@@ -45,6 +45,7 @@ import com.example.quiz.data.model.enums.PariStatut;
import com.example.quiz.databinding.FragmentBetValidationBinding; import com.example.quiz.databinding.FragmentBetValidationBinding;
import com.example.quiz.utils.BluetoothUtils; import com.example.quiz.utils.BluetoothUtils;
import com.example.quiz.utils.Result; import com.example.quiz.utils.Result;
import com.example.quiz.utils.SharedPrefsHelper;
import com.example.quiz.viewModel.PariViewModel; import com.example.quiz.viewModel.PariViewModel;
import com.example.quiz.viewModel.SharedViewModel; import com.example.quiz.viewModel.SharedViewModel;
import com.google.android.material.appbar.MaterialToolbar; import com.google.android.material.appbar.MaterialToolbar;
@@ -77,20 +78,24 @@ public class BetValidation extends Fragment {
private AlertDialog dialog; private AlertDialog dialog;
private int nombreX;
private boolean order; private boolean order;
private long mise;
private TypeOfBet typeOfBet; private TypeOfBet typeOfBet;
SharedPrefsHelper prefsHelper;
private Reunion reunion; private Reunion reunion;
private Course course; private Course course;
private int coeff; private int coeff;
private int mise;
private ActivityResultLauncher<Intent> enableBluetoothLauncher; private ActivityResultLauncher<Intent> enableBluetoothLauncher;
@@ -114,6 +119,7 @@ public class BetValidation extends Fragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
prefsHelper = SharedPrefsHelper.getInstance(getContext());
} }
@Override @Override
@@ -139,8 +145,8 @@ public class BetValidation extends Fragment {
return; return;
} }
coeff = Integer.parseInt(charSequence.toString()); coeff = Integer.parseInt(charSequence.toString());
calculateMise(selectedHorses.getValue().size()); calculateMise(selectedHorses.getValue());
binding.mise.setText(String.valueOf(mise+" CFA"));
} }
@Override @Override
@@ -180,7 +186,15 @@ public class BetValidation extends Fragment {
textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); textView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
textView.setOnClickListener(v -> { textView.setOnClickListener(v -> {
final List<String> horses = new ArrayList<>(selectedHorses.getValue()); final List<String> 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); horses.remove(horse);
selectedHorses.setValue(horses); selectedHorses.setValue(horses);
v.setSelected(false); v.setSelected(false);
@@ -196,15 +210,27 @@ public class BetValidation extends Fragment {
.collect(Collectors.joining("-")); .collect(Collectors.joining("-"));
binding.combination.setText( combinationText); binding.combination.setText( combinationText);
}); });
return textView; return textView;
} }
boolean _notClickable(List<String> 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 @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
shared = new ViewModelProvider(requireActivity()).get(SharedViewModel.class); shared = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
setSelectedTypeOfBetImage();
pariViewModel = new ViewModelProvider(this).get(PariViewModel.class); pariViewModel = new ViewModelProvider(this).get(PariViewModel.class);
typeOfBet = shared.typeOfBet.getValue(); typeOfBet = shared.typeOfBet.getValue();
reunion = shared.selectedReunion.getValue(); reunion = shared.selectedReunion.getValue();
@@ -241,8 +267,12 @@ public class BetValidation extends Fragment {
selectedHorses.observe(getViewLifecycleOwner(), new Observer<List<String>>() { selectedHorses.observe(getViewLifecycleOwner(), new Observer<List<String>>() {
@Override @Override
public void onChanged(List<String> horses) { public void onChanged(List<String> horses) {
calculateMise(horses.size()); calculateMise(horses);
binding.mise.setText(String.valueOf(mise+" CFA")); 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()){ if(shared.typeOfBet.getValue().getNumberOfHorse() > 2 && horses.size() >= shared.typeOfBet.getValue().getNumberOfHorse()){
binding.order.setVisibility(View.VISIBLE); binding.order.setVisibility(View.VISIBLE);
}else{ }else{
@@ -252,8 +282,7 @@ public class BetValidation extends Fragment {
}); });
binding.order.setOnCheckedChangeListener((buttonView, isChecked) -> { binding.order.setOnCheckedChangeListener((buttonView, isChecked) -> {
order = isChecked; order = isChecked;
calculateMise(selectedHorses.getValue().size()); calculateMise(selectedHorses.getValue());
binding.mise.setText(String.valueOf(mise+" CFA"));
}); });
binding.betValidateBtn.setOnClickListener(v->{ binding.betValidateBtn.setOnClickListener(v->{
@@ -274,10 +303,10 @@ public class BetValidation extends Fragment {
} }
Pari pari = new Pari( Pari pari = new Pari(
generate12Digits(), generate12Digits(),
shared.typeOfBet.getValue().getName(), shared.typeOfBet.getValue().getName(),
"GAGNANT",
mise, mise,
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").format(LocalDateTime.now()), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss").format(LocalDateTime.now()),
true, true,
@@ -285,25 +314,11 @@ public class BetValidation extends Fragment {
new PariCourseDto(shared.selectedCourse.getValue().getId()), new PariCourseDto(shared.selectedCourse.getValue().getId()),
selectedHorses.getValue(), selectedHorses.getValue(),
order?new ArrayList<String>(): selectedHorses.getValue(), order?new ArrayList<String>(): selectedHorses.getValue(),
order, !order,
"MULTI_4" "MULTI_4",
prefsHelper.get("code")
); );
pariViewModel.createPari(pari).observe(getViewLifecycleOwner(),new Observer<Result<Pari>>() { _showPariDialog(pari);
@Override
public void onChanged(Result<Pari> 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;
}
}
});
}); });
binding.backBtn.setOnClickListener(v->{ 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 { public void printPari(Pari pari) throws WriterException {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo); Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pmu_logo);
Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100); Bitmap barcode = generateBarcodeBitmap(pari.getNumeroTicket(), 384, 100);
@@ -332,15 +367,16 @@ public class BetValidation extends Fragment {
tspl.append("--------------------------------\n"); tspl.append("--------------------------------\n");
boolean isElargie = selectedHorses.getValue().size()>shared.typeOfBet.getValue().getNumberOfHorse(); boolean isElargie = selectedHorses.getValue().size()>shared.typeOfBet.getValue().getNumberOfHorse();
tspl.append(isElargie?pari.getTypePari()+"/Elargie":pari.getTypePari()).append("\n"); tspl.append(isElargie?pari.getTypePari()+"/Elargie":pari.getTypePari()).append("\n");
tspl.append(order?"COMBINAISON COMPLETE"+"\n":"");
String combinationText = selectedHorses.getValue().stream() String combinationText = selectedHorses.getValue().stream()
.map(String::valueOf) .map(String::valueOf)
.collect(Collectors.joining("-")); .collect(Collectors.joining("-"));
tspl.append(combinationText).append("\n"); tspl.append(combinationText).append("\n");
tspl.append("COEF: "+String.valueOf(coeff)).append(".0").append("\n"); tspl.append("COEF: "+String.valueOf(coeff)).append(".0").append("\n");
tspl.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("-------------------------------\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"); tspl.append("DATE: ").append(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss").format(LocalDateTime.now())).append("\n");
if (BluetoothUtils.needsBluetoothPermissions()) { if (BluetoothUtils.needsBluetoothPermissions()) {
if (!BluetoothUtils.hasBluetoothPermission(requireContext())) { if (!BluetoothUtils.hasBluetoothPermission(requireContext())) {
@@ -378,7 +414,7 @@ public class BetValidation extends Fragment {
TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff); TextView aler_coeff = (TextView) view.findViewById(R.id.alert_coeff);
aler_coeff.setText("Coef:"+String.valueOf(coeff)); aler_coeff.setText("Coef:"+String.valueOf(coeff));
TextView alert_montant = (TextView) view.findViewById(R.id.alert_montant); 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()); AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setView(view); builder.setView(view);
builder.setCancelable(false); builder.setCancelable(false);
@@ -387,22 +423,35 @@ public class BetValidation extends Fragment {
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
view.findViewById(R.id.alert_validate).setOnClickListener(v->{ view.findViewById(R.id.alert_validate).setOnClickListener(v->{
pariViewModel.createPari(pari).observe(getViewLifecycleOwner(),new Observer<Result<Pari>>() {
@Override
public void onChanged(Result<Pari> 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 { try {
printPari(pari); printPari(pari);
dialog.dismiss(); dialog.dismiss();
} catch (WriterException e) { } catch (WriterException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
break;
}
}
});
}); });
view.findViewById(R.id.alert_cancel).setOnClickListener(v -> { view.findViewById(R.id.alert_cancel).setOnClickListener(v -> {
dialog.dismiss(); dialog.dismiss();
}); });
dialog.show();
} }
void _initializeToZero(){ void _initializeToZero(){
mise = 0;
binding.mise.setText(String.valueOf(mise+" CFA"));
selectedHorses.setValue(List.of()); selectedHorses.setValue(List.of());
binding.combination.setText(""); binding.combination.setText("");
binding.order.setChecked(false); binding.order.setChecked(false);
@@ -413,49 +462,60 @@ public class BetValidation extends Fragment {
setupNumberGrid(binding.gridNumbers); setupNumberGrid(binding.gridNumbers);
} }
public void calculateMise(int nombreChevauxSelectionnes){ public void calculateMise(List<String> selectedHorses){
if(typeOfBet.getNumberOfHorse() == 1){ _notClickable(selectedHorses);
if(nombreChevauxSelectionnes==1){ int nombreChevauxSelectionnes = selectedHorses.size();
mise = 300; 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(typeOfBet.getNumberOfHorse() == 2){ if(typeOfBetHorses == 2){
if(nombreChevauxSelectionnes == 2){
mise = 400;
}
if(nombreChevauxSelectionnes > 2){
mise = 400 + (nombreChevauxSelectionnes - 2)*300;
}
}
if(typeOfBet.getNumberOfHorse() == 3){
if(nombreChevauxSelectionnes == 3){
mise = 500; mise = 500;
} }else{
if(nombreChevauxSelectionnes > 3){ if(typeOfBetHorses == 5){
mise = 500 + (nombreChevauxSelectionnes - 3)*500; mise = 300;
}else{
mise = 200;
} }
} }
if(typeOfBet.getNumberOfHorse() == 4){ mise = mise * coeff;
if(nombreChevauxSelectionnes == 4){ if(nombreX>0){
mise = 600; if(nombreChevauxSelectionnes == typeOfBetHorses){
mise = mise * _calculateArrangement((partants - (typeOfBetHorses-nombreX)), nombreX);
}else{
mise = mise * _calculateArrangement(nombreChevauxSelectionnes - typeOfBetHorses , nombreX);
} }
if(nombreChevauxSelectionnes > 4){ if(order){
mise = 600 + (nombreChevauxSelectionnes - 4)*600; mise = mise * _calculateArrangement(typeOfBetHorses, (typeOfBetHorses-nombreX));
} }
this.mise = mise;
binding.mise.setText(mise+" CFA");
return;
} }
if(typeOfBet.getNumberOfHorse() == 5){ mise = mise * _calculateCombinaison(nombreChevauxSelectionnes, typeOfBetHorses);
if(nombreChevauxSelectionnes == 5){ if(order){
mise = 1200; mise = mise * _calculateArrangement(nombreChevauxSelectionnes, typeOfBetHorses);
} }
if(nombreChevauxSelectionnes > 5){ this.mise = mise;
mise = 1200 + (nombreChevauxSelectionnes - 5)*1200; binding.mise.setText(mise+" CFA");
}
}
mise = order?mise * coeff * _calculateFactorial(shared.typeOfBet.getValue().getNumberOfHorse()):mise * coeff;
} }
Integer _calculateFactorial(int n){ Long _calculateArrangement(int n, int k){
int f = 1; 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){ if(n == 0){
return f; return f;
} }

View File

@@ -78,6 +78,14 @@ public class Caisse extends Fragment {
.addToBackStack(null) .addToBackStack(null)
.commit(); .commit();
}); });
binding.lastBetsBtn.setOnClickListener(v -> {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.nav_host_fragment_content_main, DerniersParis.newInstance())
.addToBackStack(null)
.commit();
});
} }
@Override @Override

View File

@@ -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<Result<List<Pari>>>() {
@Override
public void onChanged(Result<List<Pari>> 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");
}
}
}

View File

@@ -92,17 +92,17 @@ public class ListOfTypeOfBets extends Fragment {
), ),
new TypeOfBet( new TypeOfBet(
"Tierce", "Tierce",
"TRIPLET", "TIERCE",
3 3
), ),
new TypeOfBet( new TypeOfBet(
"Quarte +", "Quarte +",
"QUARTE_PLUS", "QUARTE",
4 4
), ),
new TypeOfBet( new TypeOfBet(
"Quinte +", "Quinte +",
"QUINTE_PLUS", "QUINTE",
5 5
) )
); );
@@ -129,7 +129,7 @@ public class ListOfTypeOfBets extends Fragment {
}); });
Button btnValidate = binding.btnValidate; Button btnValidate = binding.btnValidate;
btnValidate.setOnClickListener(v->{ btnValidate.setOnClickListener(v->{
if(shared.typeOfBet == null){ if(shared.typeOfBet.getValue() == null){
Toast.makeText(getContext(),"Aucun Type de jeu choisi", Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(),"Aucun Type de jeu choisi", Toast.LENGTH_SHORT).show();
return; return;
} }

View File

@@ -135,10 +135,12 @@ public class PageQuiz extends AppCompatActivity {
private void loginSuccess(LoginResponse loginResponse){ private void loginSuccess(LoginResponse loginResponse){
prefsHelper.save("id", String.valueOf(loginResponse.getId()));
prefsHelper.save("firstName", loginResponse.getPrenom()); prefsHelper.save("firstName", loginResponse.getPrenom());
prefsHelper.save("lastName", loginResponse.getNom()); prefsHelper.save("lastName", loginResponse.getNom());
prefsHelper.save("profile", loginResponse.getProfile()); prefsHelper.save("profile", loginResponse.getProfile());
prefsHelper.save("limit", String.valueOf(loginResponse.getLimiteSuperieure())); prefsHelper.save("limit", String.valueOf(loginResponse.getLimiteSuperieure()));
prefsHelper.save("code", loginResponse.getCode());
} }
@Override @Override

View File

@@ -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<ProcessCameraProvider> 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);
}
}

View File

@@ -9,26 +9,39 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; 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.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast; import android.widget.Toast;
import com.example.quiz.databinding.FragmentSoldBinding; 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 com.google.android.material.appbar.MaterialToolbar;
import java.util.Calendar; import java.util.Calendar;
import dagger.hilt.android.AndroidEntryPoint;
/** /**
* A simple {@link Fragment} subclass. * A simple {@link Fragment} subclass.
* Use the {@link Sold#newInstance} factory method to * Use the {@link Sold#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
@AndroidEntryPoint
public class Sold extends Fragment { public class Sold extends Fragment {
FragmentSoldBinding binding; FragmentSoldBinding binding;
PariViewModel pariViewModel;
SharedPrefsHelper prefsHelper;
public Sold() { public Sold() {
// Required empty public constructor // Required empty public constructor
} }
@@ -44,6 +57,7 @@ public class Sold extends Fragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
prefsHelper = SharedPrefsHelper.getInstance(getContext());
AppCompatActivity activity = (AppCompatActivity) getActivity(); AppCompatActivity activity = (AppCompatActivity) getActivity();
if(activity != null){ if(activity != null){
MaterialToolbar toolbar = activity.findViewById(R.id.toolbar); MaterialToolbar toolbar = activity.findViewById(R.id.toolbar);
@@ -66,6 +80,7 @@ public class Sold extends Fragment {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
pariViewModel = new ViewModelProvider(this).get(PariViewModel.class);
binding.btnByCourse.setOnClickListener(v -> { binding.btnByCourse.setOnClickListener(v -> {
FragmentManager fragmentManager = getParentFragmentManager(); FragmentManager fragmentManager = getParentFragmentManager();
SoldByCourse soldByCourse = SoldByCourse.newInstance(); SoldByCourse soldByCourse = SoldByCourse.newInstance();
@@ -86,14 +101,26 @@ public class Sold extends Fragment {
DatePickerDialog datePickerDialog = new DatePickerDialog( DatePickerDialog datePickerDialog = new DatePickerDialog(
getContext(), getContext(),
(view, year, month, dayOfMonth) -> { (view, year, month, dayOfMonth) -> {
String date = dayOfMonth + "/" + (month + 1) + "/" + year; String date = year + "-" + (month + 1) + "-" + dayOfMonth;
//Toast.makeText(getContext(), date, Toast.LENGTH_SHORT).show(); pariViewModel.getSoldeByDay(prefsHelper.get("code"), date).observe(getViewLifecycleOwner(), new Observer<Result<Double>>() {
new AlertDialog.Builder(getContext()) @Override
.setTitle("Solde") public void onChanged(Result<Double> doubleResult) {
.setMessage("Solde la course 3000CFA") switch (doubleResult.status){
.setPositiveButton("Ok", (dialog, which)->{ case LOADING:{
dialog.dismiss(); Toast.makeText(getContext(), "En cours", Toast.LENGTH_SHORT).show();
}).show(); break;
}
case ERROR:{
Log.d("Response", doubleResult.message);
break;
}
case SUCCESS:{
_showSold(doubleResult.data);
break;
}
}
}
});
}, },
calendar.get(Calendar.YEAR), calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH), calendar.get(Calendar.MONTH),
@@ -102,4 +129,13 @@ public class Sold extends Fragment {
datePickerDialog.show(); datePickerDialog.show();
} }
void _showSold(double solde){
new AlertDialog.Builder(getContext())
.setTitle("Solde")
.setMessage("Solde la course "+solde)
.setPositiveButton("Ok", (dialog, which)->{
dialog.dismiss();
}).show();
}
} }

View File

@@ -6,26 +6,35 @@ import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.Toast;
import com.example.quiz.databinding.FragmentSoldByCourseBinding; 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. * A simple {@link Fragment} subclass.
* Use the {@link SoldByCourse#newInstance} factory method to * Use the {@link SoldByCourse#newInstance} factory method to
* create an instance of this fragment. * create an instance of this fragment.
*/ */
@AndroidEntryPoint
public class SoldByCourse extends Fragment { public class SoldByCourse extends Fragment {
FragmentSoldByCourseBinding binding; FragmentSoldByCourseBinding binding;
// TODO: Rename parameter arguments, choose names that match PariViewModel pariViewModel;
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1"; SharedPrefsHelper prefsHelper;
private static final String ARG_PARAM2 = "param2";
public static SoldByCourse newInstance() { public static SoldByCourse newInstance() {
@@ -39,6 +48,7 @@ public class SoldByCourse extends Fragment {
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
prefsHelper = SharedPrefsHelper.getInstance(getContext());
} }
@Override @Override
@@ -52,19 +62,43 @@ public class SoldByCourse extends Fragment {
@Override @Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
pariViewModel = new ViewModelProvider(this).get(PariViewModel.class);
binding.btnCheckBalance.setOnClickListener(v -> { binding.btnCheckBalance.setOnClickListener(v -> {
if(binding.etRaceNumber.getText().toString().isEmpty()){ if(binding.etRaceNumber.getText().toString().isEmpty()){
binding.etRaceNumber.setError("Veuillez entrer un numéro de course"); binding.etRaceNumber.setError("Veuillez entrer un numéro de course");
return; return;
} }
pariViewModel.getSoldeByCourse(prefsHelper.get("code"), binding.etRaceNumber.getText().toString()).observe(getViewLifecycleOwner(), new Observer<Result<Double>>() {
@Override
public void onChanged(Result<Double> 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()) new AlertDialog.Builder(getContext())
.setTitle("Solde") .setTitle("Solde")
.setMessage("Solde la course 3000CFA") .setMessage("Solde la course "+solde)
.setPositiveButton("Ok", (dialog, which) -> { .setPositiveButton("Ok", (dialog, which) -> {
binding.etRaceNumber.setText(""); binding.etRaceNumber.setText("");
dialog.dismiss(); dialog.dismiss();
}) })
.show(); .show();
});
} }
} }

View File

@@ -51,6 +51,13 @@ public class WinTicket extends Fragment {
binding.winTicketBtnBack.setOnClickListener(v -> { binding.winTicketBtnBack.setOnClickListener(v -> {
getActivity().onBackPressed(); getActivity().onBackPressed();
}); });
binding.scanTicketBtn.setOnClickListener(v ->{
ScannerDialog scannerDialog = new ScannerDialog();
scannerDialog.setOnBarcodeScannedListener(code -> {
binding.referenceTicket.setText(code);
});
scannerDialog.show(getParentFragmentManager(), "scanner");
});
} }
@Override @Override

View File

@@ -14,6 +14,8 @@ import com.example.quiz.data.model.Course;
import com.example.quiz.viewModel.SharedViewModel; import com.example.quiz.viewModel.SharedViewModel;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BetsAdapter extends RecyclerView.Adapter<BetsAdapter.BetViewHolder> { public class BetsAdapter extends RecyclerView.Adapter<BetsAdapter.BetViewHolder> {
@@ -51,7 +53,12 @@ public class BetsAdapter extends RecyclerView.Adapter<BetsAdapter.BetViewHolder>
public void onBindViewHolder(@NonNull BetViewHolder holder, int position) { public void onBindViewHolder(@NonNull BetViewHolder holder, int position) {
Course bet = bets.get(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()); holder.tvName.setText(bet.getNom());
if (shared != null && shared.selectedReunion.getValue() != null) { if (shared != null && shared.selectedReunion.getValue() != null) {

View File

@@ -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<LastBetsAdapter.LastBetsViewHolder> {
private List<Pari> 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<Pari> 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<Pari> 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<String> 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);
}
}
}

View File

@@ -7,7 +7,6 @@ import java.util.Map;
public class Pari { public class Pari {
private String numeroTicket; private String numeroTicket;
private String typePari; private String typePari;
private String typeFormule;
private double mise; private double mise;
private String datePari; private String datePari;
private boolean estPaye; private boolean estPaye;
@@ -18,10 +17,11 @@ public class Pari {
private boolean validationOrdreExact; private boolean validationOrdreExact;
private String typeMulti; private String typeMulti;
public Pari(String numeroTicket, String typePari, String typeFormule, double mise, String datePari, boolean estPaye, boolean estRembourse, PariCourseDto course, List<String> chevauxSelectionnes, List<String> 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<String> chevauxSelectionnes, List<String> ordrePredit, boolean validationOrdreExact, String typeMulti, String createdBy) {
this.numeroTicket = numeroTicket; this.numeroTicket = numeroTicket;
this.typePari = typePari; this.typePari = typePari;
this.typeFormule = typeFormule;
this.mise = mise; this.mise = mise;
this.datePari = datePari; this.datePari = datePari;
this.estPaye = estPaye; this.estPaye = estPaye;
@@ -31,6 +31,7 @@ public class Pari {
this.ordrePredit = ordrePredit; this.ordrePredit = ordrePredit;
this.validationOrdreExact = validationOrdreExact; this.validationOrdreExact = validationOrdreExact;
this.typeMulti = typeMulti; this.typeMulti = typeMulti;
this.createdBy = createdBy;
} }
public String getNumeroTicket() { public String getNumeroTicket() {
@@ -49,14 +50,6 @@ public class Pari {
this.typePari = typePari; this.typePari = typePari;
} }
public String getTypeFormule() {
return typeFormule;
}
public void setTypeFormule(String typeFormule) {
this.typeFormule = typeFormule;
}
public double getMise() { public double getMise() {
return mise; return mise;
} }
@@ -128,4 +121,12 @@ public class Pari {
public void setTypeMulti(String typeMulti) { public void setTypeMulti(String typeMulti) {
this.typeMulti = typeMulti; this.typeMulti = typeMulti;
} }
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
} }

View File

@@ -3,10 +3,43 @@ package com.example.quiz.data.model.dtos;
public class PariCourseDto { public class PariCourseDto {
private int id; 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) { public PariCourseDto(int id) {
this.id = 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() { public int getId() {
return id; return id;
} }

View File

@@ -20,7 +20,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
@Module @Module
@InstallIn(SingletonComponent.class) @InstallIn(SingletonComponent.class)
public class ApiClient { 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 @Provides
@Singleton @Singleton

View File

@@ -12,7 +12,9 @@ import retrofit2.Call;
import retrofit2.http.Body; import retrofit2.http.Body;
import retrofit2.http.GET; import retrofit2.http.GET;
import retrofit2.http.POST; import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path; import retrofit2.http.Path;
import retrofit2.http.Query;
public interface ApiService { public interface ApiService {
@GET("reunions") @GET("reunions")
@@ -26,4 +28,17 @@ public interface ApiService {
@POST("auth/agent/login") @POST("auth/agent/login")
Call<LoginResponse> login(@Body LoginPayload loginPayload); Call<LoginResponse> login(@Body LoginPayload loginPayload);
@GET("pari/created-by/{created-by}/today")
Call<List<Pari>> derniersParis(@Path("created-by") String createdBy);
@PUT("pari/annuler/{numeroTicket}")
Call<Pari> annulerPari(@Path("numeroTicket") String numeroTicket);
@GET("pari/solde/{createdBy}/course/{courseId}")
Call<Double> getSoldeByCourse(@Path("createdBy") String createdBy, @Path("courseId") String courseId);
@GET("pari/solde/{createdBy}")
Call<Double> getSoldeByDay(@Path("createdBy") String createdBy, @Query("date") String day);
} }

View File

@@ -10,6 +10,8 @@ import com.example.quiz.data.model.Pari;
import com.example.quiz.data.remote.ApiService; import com.example.quiz.data.remote.ApiService;
import com.example.quiz.utils.Result; import com.example.quiz.utils.Result;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import retrofit2.Call; import retrofit2.Call;
@@ -57,5 +59,111 @@ public class PariRepository {
return pariResponse; return pariResponse;
} }
public LiveData<Result<List<Pari>>> derniersParis(String createdBy){
MutableLiveData<Result<List<Pari>>> derniersParis = new MutableLiveData<>();
derniersParis.setValue(Result.loading());
apiService.derniersParis(createdBy).enqueue(new Callback<List<Pari>>() {
@Override
public void onResponse(Call<List<Pari>> call, Response<List<Pari>> 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<List<Pari>> call, Throwable throwable) {
derniersParis.postValue(Result.error(throwable.getMessage()));
}
});
return derniersParis;
}
public LiveData<Result<Pari>> annulerPari(String numeroTicket){
MutableLiveData<Result<Pari>> pariResponse = new MutableLiveData<>();
pariResponse.setValue(Result.loading());
apiService.annulerPari(numeroTicket).enqueue(new Callback<Pari>(){
@Override
public void onResponse(Call<Pari> call, Response<Pari> 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<Pari> call, Throwable throwable) {
pariResponse.postValue(Result.error(throwable.getMessage()));
}
});
return pariResponse;
}
public LiveData<Result<Double>> getSoldeByCourse(String createdBy, String courseId){
MutableLiveData<Result<Double>> solde = new MutableLiveData<>();
solde.setValue(Result.loading());
apiService.getSoldeByCourse(createdBy, courseId).enqueue(new Callback<Double>() {
@Override
public void onResponse(Call<Double> call, Response<Double> 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<Double> call, Throwable throwable) {
solde.postValue(Result.error(throwable.getMessage()));
}
});
return solde;
}
public LiveData<Result<Double>> getSoldeByDay(String createdBy, String day){
MutableLiveData<Result<Double>> solde = new MutableLiveData<>();
solde.setValue(Result.loading());
apiService.getSoldeByDay(createdBy, day).enqueue(new Callback<Double>() {
@Override
public void onResponse(Call<Double> call, Response<Double> 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<Double> call, Throwable throwable) {
solde.postValue(Result.error(throwable.getMessage()));
}
});
return solde;
}
} }

View File

@@ -7,6 +7,8 @@ import com.example.quiz.data.model.Pari;
import com.example.quiz.data.repository.PariRepository; import com.example.quiz.data.repository.PariRepository;
import com.example.quiz.utils.Result; import com.example.quiz.utils.Result;
import java.util.List;
import javax.inject.Inject; import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel; import dagger.hilt.android.lifecycle.HiltViewModel;
@@ -16,6 +18,14 @@ public class PariViewModel extends ViewModel {
private final PariRepository pariRepository; private final PariRepository pariRepository;
private LiveData<Result<Pari>> pari; private LiveData<Result<Pari>> pari;
private LiveData<Result<List<Pari>>> derniersParis;
private LiveData<Result<Pari>> pariAnnule;
private LiveData<Result<Double>> solde;
private LiveData<Result<Double>> soldeByDay;
@Inject @Inject
public PariViewModel(PariRepository repository){ public PariViewModel(PariRepository repository){
this.pariRepository = repository; this.pariRepository = repository;
@@ -27,4 +37,32 @@ public class PariViewModel extends ViewModel {
} }
return this.pari; return this.pari;
} }
public LiveData<Result<List<Pari>>> getDerniersParis(String createdBy){
if(derniersParis == null){
derniersParis = pariRepository.derniersParis(createdBy);
}
return pariRepository.derniersParis(createdBy);
}
public LiveData<Result<Pari>> annulerPari(String numeroTicket){
if(pariAnnule == null){
pariAnnule = pariRepository.annulerPari(numeroTicket);
}
return pariAnnule;
}
public LiveData<Result<Double>> getSoldeByCourse(String createdBy, String courseId){
if(solde == null){
solde = pariRepository.getSoldeByCourse(createdBy, courseId);
}
return solde;
}
public LiveData<Result<Double>> getSoldeByDay(String createdBy, String day){
if(soldeByDay == null){
soldeByDay = pariRepository.getSoldeByDay(createdBy, day);
}
return soldeByDay;
}
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -21,6 +21,7 @@
android:textColor="@color/primary_green"> android:textColor="@color/primary_green">
</TextView> </TextView>
<EditText <EditText
android:id="@+id/reference_ticket"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="40dp" android:layout_height="40dp"
android:hint="Reference Ticket" android:hint="Reference Ticket"

View File

@@ -1,39 +1,59 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:background="@color/login_background"
android:id="@+id/login_container"
tools:context=".BetValidation">
<!-- SCROLL CONTENT -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/gray" android:background="@color/gray"
android:gravity="center_horizontal" android:paddingHorizontal="5dp"
android:orientation="vertical" android:layout_above="@+id/bottom_buttons">
android:paddingHorizontal="5dp">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical" android:orientation="vertical"
android:paddingHorizontal="15dp" android:paddingBottom="30dp">
tools:ignore="UselessParent"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/ic_type_of_bet"
android:layout_width="120dp"
android:layout_height="90dp" />
<View
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView <TextView
android:id="@+id/horseName" android:id="@+id/elargie"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="15dp" android:textSize="18sp"
android:layout_marginBottom="5dp"
android:textColor="@color/primary_green" android:textColor="@color/primary_green"
android:textFontWeight="300" android:textFontWeight="300"
android:textSize="17sp"> android:text="Elargie"
android:visibility="gone" />
</TextView> </LinearLayout>
<!-- 2 : Combination -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="start" android:paddingVertical="3dp">
android:orientation="horizontal"
android:paddingVertical="8dp">
<TextView <TextView
android:id="@+id/combination" android:id="@+id/combination"
@@ -43,19 +63,17 @@
android:background="@drawable/edittext_border" android:background="@drawable/edittext_border"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingStart="10sp" android:paddingStart="10sp"
android:text=""
android:textColor="@color/primary_green" android:textColor="@color/primary_green"
android:textFontWeight="800" android:textFontWeight="800"
android:textSize="18sp" android:textSize="18sp" />
tools:ignore="RtlSymmetry"></TextView>
</LinearLayout> </LinearLayout>
<!-- 3 : Grid Numbers -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginVertical="13dp"
android:gravity="center_horizontal" android:gravity="center_horizontal"
android:orientation="horizontal"> android:layout_marginVertical="13dp">
<GridLayout <GridLayout
android:id="@+id/grid_numbers" android:id="@+id/grid_numbers"
@@ -64,13 +82,13 @@
android:useDefaultMargins="true" /> android:useDefaultMargins="true" />
</LinearLayout> </LinearLayout>
<!-- 4 : Coefficient + Tout ordre -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="16dp">
<!-- Bloc coefficient + checkbox -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -79,10 +97,7 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:background="@android:color/white" android:background="@android:color/white"
android:elevation="4dp" android:elevation="4dp"
android:layout_marginBottom="14dp" android:layout_marginBottom="14dp">
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:clipToPadding="false">
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
@@ -95,12 +110,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/coefficient" android:text="@string/coefficient"
android:textSize="15sp" android:textSize="15sp"
android:textStyle="bold" android:textStyle="bold" />
android:textColor="#444444" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -108,7 +119,6 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:padding="10dp"> android:padding="10dp">
<!-- EditText -->
<EditText <EditText
android:id="@+id/coeff" android:id="@+id/coeff"
android:layout_width="0dp" android:layout_width="0dp"
@@ -120,6 +130,7 @@
android:padding="8dp" android:padding="8dp"
android:text="1" android:text="1"
android:background="@drawable/edittext_border" /> android:background="@drawable/edittext_border" />
<CheckBox <CheckBox
android:id="@+id/order" android:id="@+id/order"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -128,9 +139,6 @@
android:visibility="gone" /> android:visibility="gone" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout>
</LinearLayout> </LinearLayout>
<!-- Mise --> <!-- Mise -->
@@ -145,10 +153,10 @@
android:gravity="center" android:gravity="center"
android:padding="12dp" android:padding="12dp"
android:background="@android:color/white" android:background="@android:color/white"
android:elevation="4dp" android:elevation="4dp" />
android:clipToPadding="false"/>
</LinearLayout> </LinearLayout>
<!-- 5 : Payment + Phone -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@@ -159,10 +167,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/edittext_border" android:background="@drawable/edittext_border"
android:defaultFocusHighlightEnabled="true"
android:entries="@array/paymentType" android:entries="@array/paymentType"
android:padding="15dp" android:padding="15dp" />
android:scrollbarSize="10dp"></Spinner>
<EditText <EditText
android:id="@+id/phoneNumber" android:id="@+id/phoneNumber"
@@ -170,15 +176,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="15dp" android:layout_marginTop="15dp"
android:background="@drawable/edittext_border" android:background="@drawable/edittext_border"
android:drawableStart="@android:drawable/stat_sys_vp_phone_call"
android:inputType="phone" android:inputType="phone"
android:padding="10dp" android:padding="10dp"
android:visibility="gone"></EditText> android:visibility="gone" />
</LinearLayout> </LinearLayout>
</LinearLayout>
</ScrollView>
<!-- FIXED BOTTOM BUTTONS -->
<LinearLayout <LinearLayout
android:id="@+id/bottom_buttons"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center" android:gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="5dp" android:padding="5dp"
@@ -186,41 +197,34 @@
<Button <Button
android:id="@+id/backBtn" android:id="@+id/backBtn"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp" android:layout_margin="4dp"
android:layout_weight="1" android:layout_weight="1"
android:backgroundTint="@color/primary_red" android:backgroundTint="@color/primary_red"
android:padding="10dp"
android:text="@string/cancel" android:text="@string/cancel"
android:textColor="@color/white" /> android:textColor="@color/white" />
<Button <Button
android:id="@+id/deleteBtn" android:id="@+id/deleteBtn"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp" android:layout_width="0dp"
android:textSize="12sp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp" android:layout_margin="4dp"
android:layout_weight="1" android:layout_weight="1"
android:backgroundTint="@android:color/holo_blue_dark" android:backgroundTint="@android:color/holo_red_light"
android:padding="10dp"
android:text="@string/delete" android:text="@string/delete"
android:textColor="@color/white" /> android:textColor="@color/white" />
<Button <Button
android:id="@+id/betValidateBtn" android:id="@+id/betValidateBtn"
style="?android:attr/buttonBarButtonStyle"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp" android:layout_margin="4dp"
android:layout_weight="1" android:layout_weight="1"
android:backgroundTint="@color/primary_green" android:backgroundTint="@color/primary_green"
android:padding="10dp"
android:text="@string/validate" android:text="@string/validate"
android:textColor="@color/white" /> android:textColor="@color/white" />
</LinearLayout> </LinearLayout>
</LinearLayout> </RelativeLayout>
</ScrollView>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DerniersParis"
android:paddingVertical="10dp"
android:background="@color/text_light_grey"
>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/last_bets_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@@ -0,0 +1,18 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/closeScanDialog"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="top|end"
android:padding="8dp"
android:src="@android:drawable/ic_menu_close_clear_cancel" />
<androidx.camera.view.PreviewView
android:id="@+id/cameraPreview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

View File

@@ -21,6 +21,7 @@
android:textColor="@color/primary_green"> android:textColor="@color/primary_green">
</TextView> </TextView>
<EditText <EditText
android:id="@+id/reference_ticket"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="40dp" android:layout_height="40dp"
android:hint="Reference Ticket" android:hint="Reference Ticket"

View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:padding="12dp"
android:layout_marginVertical="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="8dp">
<TextView
android:id="@+id/last_bet_course"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Course: 5"
android:textSize="16sp"
android:gravity="start"
android:padding="4dp" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="1dp"
android:layout_height="24dp"
android:layout_marginHorizontal="8dp"
app:dividerColor="@color/black" />
<TextView
android:id="@+id/type_of_course"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="QUARTE + TIERCE"
android:textSize="16sp"
android:gravity="end"
android:padding="4dp" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginBottom="5dp"
app:dividerColor="@color/black"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="3dp">
<TextView
android:id="@+id/reference_ticket"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="12573829288"
android:textSize="16sp"
android:gravity="start"
android:padding="4dp" />
<com.google.android.material.divider.MaterialDivider
android:layout_width="1dp"
android:layout_height="24dp"
android:layout_marginHorizontal="8dp"
app:dividerColor="@color/black" />
<TextView
android:id="@+id/last_bet_type"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TIERCE"
android:textSize="16sp"
android:textFontWeight="900"
android:gravity="end"
android:padding="4dp" />
</LinearLayout>
<TextView
android:id="@+id/last_bet_horses"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Horses: 3-7-9"
android:textSize="16sp"
android:layout_marginTop="4dp"/>
<TextView
android:id="@+id/last_bet_mise"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mise: 500 CFA"
android:textSize="16sp"
android:layout_marginTop="4dp"/>
</LinearLayout>