feat: owner input and csv export
This commit is contained in:
parent
22eaf7372f
commit
739fad458f
@ -1,31 +1,46 @@
|
||||
package dev.ninjdai.balscanner;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.navigation.NavController;
|
||||
import androidx.navigation.Navigation;
|
||||
import androidx.navigation.ui.AppBarConfiguration;
|
||||
import androidx.navigation.ui.NavigationUI;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import dev.ninjdai.balscanner.books.Book;
|
||||
import dev.ninjdai.balscanner.books.Owner;
|
||||
import dev.ninjdai.balscanner.databinding.ActivityMainBinding;
|
||||
import dev.ninjdai.balscanner.ui.home.UsersItemsAdapter;
|
||||
import dev.ninjdai.balscanner.ui.scanner.ScannerItemsAdapter;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityMainBinding binding;
|
||||
|
||||
public static ConcurrentHashMap<Owner, List<Book>> books = new ConcurrentHashMap<>();
|
||||
public static Owner avril = new Owner("Avril", "Papillon");
|
||||
public static Owner current_owner = null;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -41,8 +56,5 @@ public class MainActivity extends AppCompatActivity {
|
||||
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main);
|
||||
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
|
||||
NavigationUI.setupWithNavController(binding.navView, navController);
|
||||
|
||||
books.put(avril, new ArrayList<>());
|
||||
books.get(avril).add(new Book("Test book", "Albert", "69420", avril, 0));
|
||||
}
|
||||
}
|
@ -2,6 +2,6 @@ package dev.ninjdai.balscanner.books
|
||||
|
||||
data class Book(val title: String, val author: String, val EAN: String, val owner: Owner, var price: Int)
|
||||
|
||||
data class Owner(val firstName: String, val lastName: String) {
|
||||
val id: String = firstName[0].toString() + lastName[0].toString()
|
||||
data class Owner(var firstName: String, var lastName: String, var contact: String) {
|
||||
val id: String = firstName[0].toString().uppercase() + lastName[0].toString().uppercase()
|
||||
}
|
@ -1,20 +1,49 @@
|
||||
package dev.ninjdai.balscanner.ui.home;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.InputType;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.journeyapps.barcodescanner.ScanOptions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
import dev.ninjdai.balscanner.MainActivity;
|
||||
import dev.ninjdai.balscanner.R;
|
||||
import dev.ninjdai.balscanner.books.Book;
|
||||
import dev.ninjdai.balscanner.books.Owner;
|
||||
import dev.ninjdai.balscanner.databinding.FragmentHomeBinding;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
|
||||
private FragmentHomeBinding binding;
|
||||
private UsersItemsAdapter adapter;
|
||||
private ActivityResultLauncher<String> documentCreator;
|
||||
|
||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||
ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -24,14 +53,126 @@ public class HomeFragment extends Fragment {
|
||||
binding = FragmentHomeBinding.inflate(inflater, container, false);
|
||||
View root = binding.getRoot();
|
||||
|
||||
final TextView textView = binding.textHome;
|
||||
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
|
||||
return root;
|
||||
}
|
||||
|
||||
public void updateItems() {
|
||||
adapter.notifyItemChanged(MainActivity.books.keySet().size() - 1);
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void addOwner() {
|
||||
Owner tmpOwner = new Owner("UNK", "UNK", "");
|
||||
Activity activity = getActivity();
|
||||
if (activity==null) return;
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle("Prénom");
|
||||
|
||||
final EditText input = new EditText(getActivity());
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton("Suivant", (dialog, which) -> {
|
||||
tmpOwner.setFirstName(input.getText().toString());
|
||||
|
||||
AlertDialog.Builder lastBuilder = new AlertDialog.Builder(activity);
|
||||
lastBuilder.setTitle("Nom de famille");
|
||||
final EditText lastInput = new EditText(getActivity());
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
|
||||
lastBuilder.setView(lastInput);
|
||||
|
||||
lastBuilder.setPositiveButton("Suivant", (lDialog, lWhich) -> {
|
||||
tmpOwner.setLastName(lastInput.getText().toString());
|
||||
|
||||
AlertDialog.Builder cBuilder = new AlertDialog.Builder(activity);
|
||||
cBuilder.setTitle("Contact");
|
||||
final EditText cInput = new EditText(getActivity());
|
||||
input.setInputType(InputType.TYPE_CLASS_TEXT);
|
||||
cBuilder.setView(cInput);
|
||||
|
||||
cBuilder.setPositiveButton("Valider", (cDialog, cWhich) -> {
|
||||
tmpOwner.setContact(cInput.getText().toString());
|
||||
Owner o = new Owner(tmpOwner.getFirstName().strip(), tmpOwner.getLastName().strip(), tmpOwner.getContact().strip());
|
||||
MainActivity.books.put(o, new ArrayList<>());
|
||||
MainActivity.current_owner = o;
|
||||
adapter.setmData(new ArrayList<>(MainActivity.books.keySet()));
|
||||
adapter.notifyDataSetChanged();
|
||||
});
|
||||
cBuilder.setNegativeButton("Annuler", (cDialog, cWhich) -> cDialog.cancel());
|
||||
cBuilder.show();
|
||||
});
|
||||
lastBuilder.setNegativeButton("Annuler", (lDialog, lWhich) -> lDialog.cancel());
|
||||
lastBuilder.show();
|
||||
});
|
||||
builder.setNegativeButton("Annuler", (dialog, which) -> dialog.cancel());
|
||||
builder.show();
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.users_items);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
adapter = new UsersItemsAdapter(getContext(), new ArrayList<>(MainActivity.books.keySet()));
|
||||
|
||||
adapter.setClickListener((v, position) -> {
|
||||
Owner o = adapter.getItem(position);
|
||||
Toast.makeText(getContext(), String.format("Sélectionné %s %s", o.getFirstName(), o.getLastName()), Toast.LENGTH_SHORT).show();
|
||||
adapter.notifyDataSetChanged();
|
||||
MainActivity.current_owner = o;
|
||||
});
|
||||
adapter.setLongClickListener((v, position) -> {
|
||||
Toast.makeText(getContext(), "Removed " + adapter.getItem(position), Toast.LENGTH_LONG).show();
|
||||
adapter.removeItem(position);
|
||||
adapter.notifyItemRemoved(position);
|
||||
return true;
|
||||
});
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
documentCreator = registerForActivityResult(new ActivityResultContracts.CreateDocument("text/csv"), this::onDocumentActivityResult);
|
||||
|
||||
Button userButton = view.findViewById(R.id.user_button);
|
||||
userButton.setOnClickListener(v -> {
|
||||
addOwner();
|
||||
});
|
||||
Button exportButton = view.findViewById(R.id.export_button);
|
||||
exportButton.setOnClickListener(v -> {
|
||||
documentCreator.launch("export.csv");
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
binding = null;
|
||||
}
|
||||
|
||||
private void onDocumentActivityResult(Uri result) {
|
||||
if (result == null) {
|
||||
Toast.makeText(getContext(), "Export annulé", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
OutputStream stream = getActivity().getContentResolver().openOutputStream(result);
|
||||
if (stream==null) {
|
||||
Toast.makeText(getContext(), "Erreur lors de l'ouverture du fichier", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
for (Owner owner: MainActivity.books.keySet()) {
|
||||
for (Book book: Objects.requireNonNull(MainActivity.books.get(owner))) {
|
||||
@SuppressLint("DefaultLocale")
|
||||
String line = String.format(";%s;%s;%s;%d;;%s;;%s;%s%n",
|
||||
owner.getLastName(), owner.getFirstName(), owner.getContact(), book.getPrice(), book.getEAN(), book.getTitle(), book.getAuthor());
|
||||
stream.write(line.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
stream.flush();
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e("BALScanner", "onDocumentActivityResult", e);
|
||||
Toast.makeText(getContext(), "Erreur lors de la création du fichier", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package dev.ninjdai.balscanner.ui.home;
|
||||
|
||||
import android.content.Context;
|
||||
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 java.util.List;
|
||||
|
||||
import dev.ninjdai.balscanner.MainActivity;
|
||||
import dev.ninjdai.balscanner.R;
|
||||
import dev.ninjdai.balscanner.books.Book;
|
||||
import dev.ninjdai.balscanner.books.Owner;
|
||||
|
||||
public class UsersItemsAdapter extends RecyclerView.Adapter<UsersItemsAdapter.ViewHolder> {
|
||||
|
||||
private List<Owner> mData;
|
||||
private final LayoutInflater mInflater;
|
||||
private ItemClickListener mClickListener;
|
||||
private ItemLongClickListener mLongClickListener;
|
||||
|
||||
// data is passed into the constructor
|
||||
public UsersItemsAdapter(Context context, List<Owner> data) {
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
this.mData = data;
|
||||
}
|
||||
|
||||
public void setmData(List<Owner> owners) {
|
||||
mData = owners;
|
||||
}
|
||||
|
||||
// inflates the row layout from xml when needed
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = mInflater.inflate(R.layout.text_row_item, parent, false);
|
||||
return new ViewHolder(view);
|
||||
}
|
||||
|
||||
// binds the data to the TextView in each row
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Owner owner = mData.get(position);
|
||||
holder.myTextView.setText(String.format("%s%s %s (%s) - %s", owner==MainActivity.current_owner ? "> " : "", owner.getFirstName(), owner.getLastName(), owner.getId(), owner.getContact()));
|
||||
}
|
||||
|
||||
// total number of rows
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mData.size();
|
||||
}
|
||||
|
||||
|
||||
// stores and recycles views as they are scrolled off screen
|
||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||
TextView myTextView;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
myTextView = itemView.findViewById(R.id.bookText);
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if (mClickListener != null) return mLongClickListener.onItemLongClick(view, getAdapterPosition());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// convenience method for getting data at click position
|
||||
Owner getItem(int id) {
|
||||
return mData.get(id);
|
||||
}
|
||||
|
||||
Owner removeItem(int id) {
|
||||
MainActivity.books.remove(mData.get(id));
|
||||
return mData.remove(id);
|
||||
}
|
||||
|
||||
// allows clicks events to be caught
|
||||
void setClickListener(ItemClickListener itemClickListener) {
|
||||
this.mClickListener = itemClickListener;
|
||||
}
|
||||
void setLongClickListener(ItemLongClickListener itemLongClickListener) {
|
||||
this.mLongClickListener = itemLongClickListener;
|
||||
}
|
||||
|
||||
// parent activity will implement this method to respond to click events
|
||||
public interface ItemClickListener {
|
||||
void onItemClick(View view, int position);
|
||||
}
|
||||
public interface ItemLongClickListener {
|
||||
boolean onItemLongClick(View view, int position);
|
||||
}
|
||||
}
|
@ -53,7 +53,7 @@ public class ScannerFragment extends Fragment {
|
||||
}
|
||||
|
||||
public void updateItems() {
|
||||
adapter.notifyItemChanged(MainActivity.books.get(MainActivity.avril).size()-1);
|
||||
adapter.notifyItemChanged(MainActivity.books.get(MainActivity.current_owner).size()-1);
|
||||
}
|
||||
|
||||
private void noBookFoundToast() {
|
||||
@ -73,7 +73,7 @@ public class ScannerFragment extends Fragment {
|
||||
|
||||
builder.setPositiveButton("Valider", (dialog, which) -> {
|
||||
book.setPrice(Integer.parseInt(input.getText().toString()));
|
||||
MainActivity.books.computeIfPresent(MainActivity.avril, ((owner, ownerBooks) -> {
|
||||
MainActivity.books.computeIfPresent(MainActivity.current_owner, ((owner, ownerBooks) -> {
|
||||
ownerBooks.add(book);
|
||||
return ownerBooks;
|
||||
}));
|
||||
@ -88,9 +88,11 @@ public class ScannerFragment extends Fragment {
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.scanner_items);
|
||||
Toast.makeText(getActivity(), String.format("%s %s", MainActivity.current_owner.getFirstName(), MainActivity.current_owner.getLastName()), Toast.LENGTH_SHORT).show();
|
||||
|
||||
RecyclerView recyclerView = view.findViewById(R.id.users_items);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
adapter = new ScannerItemsAdapter(getContext(), MainActivity.books.get(MainActivity.avril));
|
||||
adapter = new ScannerItemsAdapter(getContext(), MainActivity.books.get(MainActivity.current_owner));
|
||||
|
||||
adapter.setClickListener((v, position) -> Toast.makeText(getActivity(), "Book: " + adapter.getItem(position), Toast.LENGTH_LONG).show());
|
||||
adapter.setLongClickListener((v, position) -> {
|
||||
@ -125,7 +127,7 @@ public class ScannerFragment extends Fragment {
|
||||
builder.setView(input);
|
||||
|
||||
builder.setPositiveButton("Suivant", (dialog, which) -> {
|
||||
Book book = new Book(input.getText().toString(), "Inconnu", ean, MainActivity.avril, 0);
|
||||
Book book = new Book(input.getText().toString().strip(), "Inconnu", ean, MainActivity.current_owner, 0);
|
||||
addBook(book);
|
||||
});
|
||||
builder.setNegativeButton("Annuler", (dialog, which) -> dialog.cancel());
|
||||
@ -143,7 +145,7 @@ public class ScannerFragment extends Fragment {
|
||||
if (authorRes != null) author = authorRes.getString("name");
|
||||
}
|
||||
}
|
||||
Book book = new Book(title, author, ean, MainActivity.avril, 0);
|
||||
Book book = new Book(title, author, ean, MainActivity.current_owner, 0);
|
||||
addBook(book);
|
||||
} catch (JSONException ex) {
|
||||
Log.e("App", "Failure", ex);
|
||||
|
@ -6,17 +6,29 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.home.HomeFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_home"
|
||||
android:layout_width="match_parent"
|
||||
<Button
|
||||
android:id="@+id/user_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
android:layout_marginBottom="108dp"
|
||||
android:text="@string/user_new"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/users_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/export_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="68dp"
|
||||
android:text="@string/export"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -17,7 +17,7 @@
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/scanner_items"
|
||||
android:id="@+id/users_items"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
|
@ -5,4 +5,6 @@
|
||||
|
||||
<string name="scan_new">Scan</string>
|
||||
<string name="element_text">element</string>
|
||||
<string name="user_new">Ajout</string>
|
||||
<string name="export">Export</string>
|
||||
</resources>
|
Loading…
Reference in New Issue
Block a user