mirror of
https://github.com/lucasroyerdev/stock-pignon.git
synced 2026-05-10 11:02:26 +00:00
feat: initial functional release of Stock Pignon
This commit is contained in:
304
app/src/main/java/com/stock/pignon/MainActivity.java
Normal file
304
app/src/main/java/com/stock/pignon/MainActivity.java
Normal file
@@ -0,0 +1,304 @@
|
||||
package com.stock.pignon;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.GridLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.os.Environment;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Main Activity: Central Dashboard for the application.
|
||||
* Manages category navigation and item selection within a single screen.
|
||||
*/
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
// UI Components
|
||||
private LinearLayout cartList;
|
||||
private LinearLayout homeLayout;
|
||||
private LinearLayout categoryItemsLayout;
|
||||
private LinearLayout categoriesLayout;
|
||||
private GridLayout gridPieces;
|
||||
private ImageView mainImage;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
// Hide Android bar
|
||||
View decorView = getWindow().getDecorView();
|
||||
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN;
|
||||
decorView.setSystemUiVisibility(uiOptions);
|
||||
|
||||
// View Binding
|
||||
cartList = findViewById(R.id.cartList);
|
||||
homeLayout = findViewById(R.id.homeLayout);
|
||||
categoryItemsLayout = findViewById(R.id.categoryItemsLayout);
|
||||
categoriesLayout = findViewById(R.id.categoriesLayout);
|
||||
gridPieces = findViewById(R.id.gridPieces);
|
||||
mainImage = findViewById(R.id.mainImage);
|
||||
|
||||
// Setup Back Button
|
||||
Button backBtn = findViewById(R.id.backToHomeBtn);
|
||||
if (backBtn != null) {
|
||||
backBtn.setOnClickListener(v -> showHome());
|
||||
}
|
||||
|
||||
// Copy assets to sd card if not founded
|
||||
copyAssetsIfEmpty();
|
||||
// Get data from sd card
|
||||
DataLoader.loadData();
|
||||
|
||||
// Initial UI Setup
|
||||
setupCategoriesMenu();
|
||||
loadMainImage();
|
||||
|
||||
// Initial cart visual sync
|
||||
CartViewHelper.updateCartView(cartList, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the left sidebar with category buttons using DataLoader's cache.
|
||||
*/
|
||||
private void setupCategoriesMenu() {
|
||||
List<Category> categories = DataLoader.getCategories();
|
||||
if (categories == null || categories.isEmpty()) {
|
||||
Log.w(TAG, "No categories found to display.");
|
||||
return;
|
||||
}
|
||||
|
||||
categoriesLayout.removeAllViews();
|
||||
for (Category category : categories) {
|
||||
Button btn = createCategoryButton(category);
|
||||
// On click, we show the items for this specific category
|
||||
btn.setOnClickListener(v -> showCategory(category.getName()));
|
||||
categoriesLayout.addView(btn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Styles category buttons based on the new Category getters.
|
||||
*/
|
||||
private Button createCategoryButton(Category category) {
|
||||
Button btn = new Button(this);
|
||||
btn.setText(category.getName());
|
||||
btn.setTextSize(TypedValue.COMPLEX_UNIT_SP, 24);
|
||||
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
float radiusPx = 3 * density;
|
||||
|
||||
// Apply background color with transparency (70% alpha)
|
||||
if (category.getBgColor() != null) {
|
||||
try {
|
||||
int color = Color.parseColor(category.getBgColor());
|
||||
int alpha = (int) (0.7 * 255);
|
||||
color = (color & 0x00FFFFFF) | (alpha << 24);
|
||||
|
||||
GradientDrawable shape = new GradientDrawable();
|
||||
shape.setColor(color);
|
||||
shape.setCornerRadius(radiusPx);
|
||||
btn.setBackground(shape);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error parsing bgColor for: " + category.getName());
|
||||
}
|
||||
}
|
||||
|
||||
// Apply text color
|
||||
if (category.getTextColor() != null) {
|
||||
try {
|
||||
btn.setTextColor(Color.parseColor(category.getTextColor()));
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error parsing textColor for: " + category.getName());
|
||||
}
|
||||
}
|
||||
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
);
|
||||
params.setMargins(0, 5, 0, 5);
|
||||
btn.setLayoutParams(params);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches center view to display the grid of items.
|
||||
* Uses DataLoader.getItemsForCategory() to get the merged list.
|
||||
*/
|
||||
private void showCategory(String categoryName) {
|
||||
homeLayout.setVisibility(View.GONE);
|
||||
categoryItemsLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
gridPieces.removeAllViews();
|
||||
|
||||
// Calculate item width for a 4-column grid
|
||||
int gridWidth = getResources().getDisplayMetrics().widthPixels - dpToPx(370);
|
||||
int itemWidth = gridWidth / 4;
|
||||
|
||||
// Fetch the PRE-MERGED list (globals + specifics) from DataLoader
|
||||
List<Item> itemsToDisplay = DataLoader.getItemsForCategory(categoryName);
|
||||
|
||||
for (Item item : itemsToDisplay) {
|
||||
View itemView = LayoutInflater.from(this).inflate(R.layout.item_piece, gridPieces, false);
|
||||
|
||||
// Apply width to the inflated view
|
||||
GridLayout.LayoutParams params = (GridLayout.LayoutParams) itemView.getLayoutParams();
|
||||
if (params == null) {
|
||||
params = new GridLayout.LayoutParams();
|
||||
}
|
||||
params.width = itemWidth;
|
||||
itemView.setLayoutParams(params);
|
||||
|
||||
bindItemToView(itemView, item);
|
||||
gridPieces.addView(itemView);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects Item data to the inflated layout piece.
|
||||
*/
|
||||
private void bindItemToView(View itemView, Item item) {
|
||||
TextView nom = itemView.findViewById(R.id.itemName);
|
||||
TextView prix = itemView.findViewById(R.id.itemPrice);
|
||||
ImageView img = itemView.findViewById(R.id.itemImage);
|
||||
TextView qtyView = itemView.findViewById(R.id.qtyView);
|
||||
|
||||
nom.setText(item.getName());
|
||||
prix.setText(getString(R.string.price_range, item.getMinPrice(), item.getMaxPrice(), "€"));
|
||||
|
||||
// Use your existing ImageLoader helper
|
||||
ImageLoader.loadImage(img, item.getImage(),200,200);
|
||||
|
||||
// Sync visual quantity with CartManager
|
||||
CartItem existing = CartManager.getItemByName(item.getName());
|
||||
int currentQty = (existing != null) ? existing.getQuantity() : 0;
|
||||
qtyView.setText(String.valueOf(currentQty));
|
||||
|
||||
// Listeners for + and - buttons
|
||||
itemView.findViewById(R.id.plusBtn).setOnClickListener(v -> updateItemQty(item, qtyView, 1));
|
||||
itemView.findViewById(R.id.minusBtn).setOnClickListener(v -> updateItemQty(item, qtyView, -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the local counter and the global cart state simultaneously.
|
||||
*/
|
||||
private void updateItemQty(Item item, TextView qtyView, int delta) {
|
||||
int current = Integer.parseInt(qtyView.getText().toString());
|
||||
int next = Math.max(0, current + delta);
|
||||
|
||||
qtyView.setText(String.valueOf(next));
|
||||
|
||||
// Central data update
|
||||
CartManager.addOrUpdateItem(item.getName(), item.getMinPrice(), item.getMaxPrice(), next, item.getImage());
|
||||
|
||||
// Refresh sidebar cart list
|
||||
CartViewHelper.updateCartView(cartList, this);
|
||||
}
|
||||
|
||||
private void showHome() {
|
||||
categoryItemsLayout.setVisibility(View.GONE);
|
||||
homeLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void loadMainImage() {
|
||||
// Fallback for home screen image
|
||||
ImageLoader.loadImage(mainImage, "_velo", 800,800);
|
||||
}
|
||||
|
||||
// --- Button Actions (linked via android:onClick in XML) ---
|
||||
|
||||
public void emptyCart(View view) {
|
||||
CartActionHelper.emptyCart(cartList, this);
|
||||
}
|
||||
|
||||
public void validateCart(View view) {
|
||||
CartActionHelper.validateCart(cartList, this);
|
||||
}
|
||||
|
||||
private int dpToPx(int dp) {
|
||||
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// Ensure cart is up to date if returning to the activity
|
||||
CartViewHelper.updateCartView(cartList, this);
|
||||
}
|
||||
|
||||
private void copyAssetsIfEmpty() {
|
||||
File folder = new File(Environment.getExternalStorageDirectory(), Config.EXTERNAL_DIR_NAME);
|
||||
|
||||
// First safety : is folder already in sdcard ?
|
||||
if (!folder.exists()) {
|
||||
// Second safety : are we able to create folder ?
|
||||
if (folder.mkdirs()) {
|
||||
// Copy JSON file
|
||||
copyFileFromAssets(Config.PIECES_FILE_NAME, new File(folder, Config.PIECES_FILE_NAME));
|
||||
|
||||
// Copy images subfolder
|
||||
File imgFolder = new File(folder, Config.IMAGES_SUBDIR_NAME);
|
||||
if (imgFolder.mkdirs()) {
|
||||
copyFolderFromAssets(Config.IMAGES_SUBDIR_NAME, imgFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFolderFromAssets(String assetDirName, File destDir) {
|
||||
try {
|
||||
String[] files = getAssets().list(assetDirName);
|
||||
if (files != null) {
|
||||
// For every image
|
||||
for (String fileName : files) {
|
||||
// Create source path
|
||||
String assetPath = assetDirName + "/" + fileName;
|
||||
// Create dest path
|
||||
File destFile = new File(destDir, fileName);
|
||||
// Copy
|
||||
copyFileFromAssets(assetPath, destFile);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e("MainActivity", "Erreur listing assets: " + assetDirName, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyFileFromAssets(String assetName, File destFile) {
|
||||
// Optimized read
|
||||
// Try-with-resources ensures streams are automatically closed, avoid memory leaks
|
||||
try (InputStream in = getAssets().open(assetName);
|
||||
OutputStream out = new FileOutputStream(destFile)) {
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, read);
|
||||
}
|
||||
Log.d("MainActivity", "Succès : " + assetName + " copié.");
|
||||
|
||||
} catch (IOException e) {
|
||||
Log.e("MainActivity", "Erreur copie asset: " + assetName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user