Skip to content

Commit 3896881

Browse files
author
Leshoraa
committed
feat: Enhance List Management with Quantity, Edit, and UI Improvements
This commit introduces significant enhancements to the application, focusing on improved list management functionality and a refined user interface. Key changes include: - **Added Quantity Feature:** Implemented functionality to manage item quantities directly within the list. - **Redesigned AddItemActivity & PreviewItemActivity:** Reworked the layouts and logic for adding and previewing items to support new features and improve usability. - **Improved Accent Colors:** Updated various accent colors throughout the application for a more cohesive and appealing visual experience. - **Enhanced Item Editing:** Introduced the ability to edit existing list items, including their details and quantity, directly from the list view. - **Category Text Color Update:** Adjusted text colors for categories to improve readability and visual consistency. - **New Font Integration:** Incorporated new fonts to enhance the overall aesthetic and typography of the application. - **Bug Fix:** Resolved an issue to ensure accurate discount calculations. ```
1 parent 1e3dfb0 commit 3896881

20 files changed

+1079
-393
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ dependencies {
4040
implementation(libs.material)
4141
implementation(libs.retrofit)
4242
implementation(libs.converter.gson)
43-
implementation("com.google.guava:guava:32.0.1-android")
44-
implementation("com.squareup.okhttp3:okhttp:4.9.3")
43+
implementation(libs.guava)
44+
implementation(libs.okhttp.v493)
4545
implementation(libs.activity)
4646
implementation(libs.constraintlayout)
4747
implementation(libs.firebase.crashlytics.buildtools)

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
tools:targetApi="31">
2525
<activity
2626
android:name=".PreviewItemActivity"
27-
android:exported="false" />
27+
android:exported="false"
28+
android:windowSoftInputMode="adjustResize"/>
2829
<activity
2930
android:name=".AddItemActivity"
3031
android:exported="false"

app/src/main/java/com/leshoraa/listshop/AddItemActivity.java

Lines changed: 91 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,31 @@ public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
220220

221221
binding.back.setOnClickListener(v -> onBackPressed());
222222

223+
binding.tvReducequantity.setOnClickListener(v -> {
224+
try {
225+
int currentQuantity = Integer.parseInt(binding.edtQuantity.getText().toString());
226+
227+
if (currentQuantity > 0) {
228+
currentQuantity--;
229+
binding.edtQuantity.setText(String.valueOf(currentQuantity));
230+
}
231+
232+
} catch (NumberFormatException e) {
233+
binding.edtQuantity.setText("0");
234+
}
235+
});
236+
237+
binding.tvAddquantity.setOnClickListener(v -> {
238+
try {
239+
int currentQuantity = Integer.parseInt(binding.edtQuantity.getText().toString());
240+
currentQuantity++;
241+
binding.edtQuantity.setText(String.valueOf(currentQuantity));
242+
243+
} catch (NumberFormatException e) {
244+
binding.edtQuantity.setText("1");
245+
}
246+
});
247+
223248
DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.getDefault());
224249
symbols.setGroupingSeparator('.');
225250
decimalFormat = new DecimalFormat("#,##0", symbols);
@@ -328,6 +353,8 @@ private void setupTakePictureLauncher() {
328353
binding.imageViewCaptured.setImageBitmap(capturedImageBitmap);
329354
binding.imageViewCaptured.setVisibility(View.VISIBLE);
330355
binding.cameraPreview.setVisibility(View.GONE);
356+
binding.edtQuantity.setText("1");
357+
331358
currentModelIndex = 0;
332359
analyzeImageWithGemini(capturedImageBitmap);
333360
}
@@ -748,43 +775,89 @@ private android.hardware.Camera.Size getOptimalPreviewSize(List<android.hardware
748775

749776
return optimalSize;
750777
}
778+
private String addDiscountData() {
779+
JSONArray discountsJsonArray = new JSONArray();
780+
double sumOfDiscounts = 0.0;
781+
782+
for (int i = 0; i < discountAdapter.getItemCount() - 1; i++) {
783+
String discountStr = discountAdapter.getDiscountAt(i);
784+
if (!discountStr.trim().isEmpty()) {
785+
try {
786+
double discountValue = Double.parseDouble(discountStr);
787+
if (discountValue < 0 || discountValue > 100) {
788+
Toast.makeText(this, "Discount must be between 0 and 100.", Toast.LENGTH_SHORT).show();
789+
return null;
790+
}
791+
discountsJsonArray.put(discountValue);
792+
sumOfDiscounts += discountValue;
793+
} catch (NumberFormatException | JSONException e) {
794+
Toast.makeText(this, "Invalid discount value: " + discountStr, Toast.LENGTH_SHORT).show();
795+
return null;
796+
}
797+
}
798+
}
751799

800+
if (sumOfDiscounts >= 100.0) {
801+
Toast.makeText(this, "Total discount cannot exceed 100%. Adjusting discounts.", Toast.LENGTH_SHORT).show();
802+
return null;
803+
}
804+
805+
return discountsJsonArray.toString();
806+
}
752807
private void addItemToDatabase() {
753808
String name = binding.edtTitle.getText().toString();
754809
String description = binding.edtDesc.getText().toString();
755810
String category = binding.edtCategory.getText().toString();
756-
int count = 1;
811+
812+
int count;
813+
try {
814+
count = Integer.parseInt(binding.edtQuantity.getText().toString());
815+
} catch (NumberFormatException e) {
816+
Toast.makeText(this, "Invalid quantity amount.", Toast.LENGTH_SHORT).show();
817+
return;
818+
}
819+
if (count < 1) {
820+
Toast.makeText(this, "Minimum quantity must be 1 to save the item.", Toast.LENGTH_SHORT).show();
821+
return;
822+
}
757823

758824
double price = 0.0;
759825
try {
760826
String priceString = binding.edtPrice.getText().toString();
761827
String cleanPriceString = priceString.replaceAll("[.]", "");
762-
price = Double.parseDouble(cleanPriceString);
828+
if (cleanPriceString.isEmpty()) {
829+
price = 0.0;
830+
} else {
831+
price = Double.parseDouble(cleanPriceString);
832+
}
763833
} catch (NumberFormatException e) {
764-
Toast.makeText(this, "Masukkan harga yang valid.", Toast.LENGTH_SHORT).show();
834+
Toast.makeText(this, "Please enter a valid price.", Toast.LENGTH_SHORT).show();
765835
return;
766836
}
837+
double totalBasePrice = price * count;
767838

768-
JSONArray discountsJsonArray = new JSONArray();
839+
String discountsJson = addDiscountData();
840+
if (discountsJson == null) {
841+
return;
842+
}
843+
844+
JSONArray discountsJsonArray;
769845
double sumOfDiscounts = 0.0;
770-
for (String discountStr : discountItems) {
771-
if (!discountStr.trim().isEmpty()) {
772-
try {
773-
double discountValue = Double.parseDouble(discountStr);
774-
discountsJsonArray.put(discountValue);
775-
sumOfDiscounts += discountValue;
776-
} catch (NumberFormatException | JSONException e) {
777-
Toast.makeText(this, "Nilai diskon tidak valid: " + discountStr, Toast.LENGTH_SHORT).show();
778-
return;
779-
}
846+
try {
847+
discountsJsonArray = new JSONArray(discountsJson);
848+
for (int i = 0; i < discountsJsonArray.length(); i++) {
849+
sumOfDiscounts += discountsJsonArray.getDouble(i);
780850
}
851+
} catch (JSONException e) {
852+
Toast.makeText(this, "An error occurred while processing discounts.", Toast.LENGTH_SHORT).show();
853+
return;
781854
}
782855

783856
double finalPrice;
784857
if (sumOfDiscounts >= 100.0) {
785858
finalPrice = 0.0;
786859
} else {
787-
finalPrice = calculateFinalPrice(price, discountsJsonArray);
860+
finalPrice = calculateFinalPrice(totalBasePrice, discountsJsonArray);
788861
}
789862

790863
String date = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(new Date());
@@ -800,19 +873,19 @@ private void addItemToDatabase() {
800873
newItem.setCategory(category);
801874
newItem.setImageData(imageData);
802875
newItem.setPrice(price);
803-
newItem.setDiscountsJson(discountsJsonArray.toString());
804876
newItem.setFinalPrice(finalPrice);
805877
newItem.setItemListId(item_list_id);
806878
newItem.setParentListId(parentListIdFromIntent);
807879
newItem.setTotalDiscountPercentage(sumOfDiscounts);
880+
newItem.setDiscountsJson(discountsJson);
808881

809882
long newRowId = dbHelper.addItem(newItem);
810883

811884
if (newRowId != -1) {
812-
Toast.makeText(this, "Item berhasil ditambahkan!", Toast.LENGTH_SHORT).show();
885+
Toast.makeText(this, "Item added successfully!", Toast.LENGTH_SHORT).show();
813886
finish();
814887
} else {
815-
Toast.makeText(this, "Gagal menambahkan item.", Toast.LENGTH_SHORT).show();
888+
Toast.makeText(this, "Failed to add item.", Toast.LENGTH_SHORT).show();
816889
}
817890
}
818891

app/src/main/java/com/leshoraa/listshop/ListActivity.java

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import android.view.Window;
1414
import android.view.WindowInsetsController;
1515
import android.view.WindowManager;
16+
import android.view.inputmethod.EditorInfo;
1617
import android.widget.PopupMenu;
1718
import android.widget.Toast;
1819
import android.util.Log;
@@ -124,12 +125,10 @@ protected void onCreate(Bundle savedInstanceState) {
124125

125126
binding.marketName.addTextChangedListener(new TextWatcher() {
126127
@Override
127-
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
128-
}
128+
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
129129

130130
@Override
131-
public void onTextChanged(CharSequence s, int start, int before, int count) {
132-
}
131+
public void onTextChanged(CharSequence s, int start, int before, int count) {}
133132

134133
@Override
135134
public void afterTextChanged(Editable s) {
@@ -150,22 +149,14 @@ public void afterTextChanged(Editable s) {
150149

151150
binding.todo.setOnClickListener(v -> toggleTodoVisibility());
152151

153-
binding.tvAddListBtn.setOnClickListener(v -> {
154-
String todoName = binding.edtTodo.getText().toString().trim();
155-
if (!todoName.isEmpty()) {
156-
Item newTodoItem = new Item(0, todoName, 0, false, null);
157-
newTodoItem.setParentListId(currentParentListId);
158-
long newTodoId = dbHelper.addTodoItem(newTodoItem);
159-
if (newTodoId != -1) {
160-
newTodoItem.setId((int) newTodoId);
161-
loadTodoItems();
162-
binding.edtTodo.setText("");
163-
} else {
164-
Toast.makeText(ListActivity.this, "Failed to add todo item.", Toast.LENGTH_SHORT).show();
165-
}
166-
} else {
167-
Toast.makeText(ListActivity.this, "Todo item name cannot be empty.", Toast.LENGTH_SHORT).show();
152+
binding.tvAddListBtn.setOnClickListener(v -> addTodoItemToList());
153+
154+
binding.edtTodo.setOnEditorActionListener((v, actionId, event) -> {
155+
if (actionId == EditorInfo.IME_ACTION_DONE) {
156+
addTodoItemToList();
157+
return true;
168158
}
159+
return false;
169160
});
170161

171162
binding.tvDropdownMenu.setOnClickListener(this::showPopupMenu);
@@ -198,6 +189,10 @@ private void setupRecyclerView() {
198189
intent.putExtra(EXTRA_SELECTED_ITEM_ID, selectedItem.getId());
199190
startActivity(intent);
200191
});
192+
193+
itemListAdapter.setOnItemQuantityChangeListener((itemId, newQuantity) -> {
194+
loadItems();
195+
});
201196
}
202197

203198
private void setupTodoRecyclerView() {
@@ -248,17 +243,43 @@ private void loadTodoItems() {
248243
todoList.clear();
249244
todoList.addAll(dbHelper.getTodoItemsByParentListId(currentParentListId));
250245
shopListAdapter.notifyDataSetChanged();
246+
updateShopListCount();
251247
}
252248
}
253249

254250
private void updateTotalPrice() {
255251
double total = 0.0;
256252
for (Item item : itemsList) {
257-
total += item.getFinalPrice() * item.getCount();
253+
total += item.getFinalPrice();
258254
}
259255
binding.tvTotal.setText(decimalFormat.format(total));
260256
}
261257

258+
private void addTodoItemToList() {
259+
String todoName = binding.edtTodo.getText().toString().trim();
260+
if (!todoName.isEmpty()) {
261+
Item newTodoItem = new Item(0, todoName, 0, false, null);
262+
newTodoItem.setParentListId(currentParentListId);
263+
long newTodoId = dbHelper.addTodoItem(newTodoItem);
264+
if (newTodoId != -1) {
265+
newTodoItem.setId((int) newTodoId);
266+
loadTodoItems();
267+
binding.edtTodo.setText("");
268+
} else {
269+
Toast.makeText(ListActivity.this, "Failed to add todo item.", Toast.LENGTH_SHORT).show();
270+
}
271+
} else {
272+
Toast.makeText(ListActivity.this, "Todo item name cannot be empty.", Toast.LENGTH_SHORT).show();
273+
}
274+
}
275+
276+
private void updateShopListCount() {
277+
int count = todoList.size();
278+
binding.tvShoplistCount.setText(String.valueOf(count));
279+
//binding.flShoplistCount.setVisibility(count > 0 ? View.VISIBLE : View.GONE); // Hide if count is 0
280+
}
281+
282+
262283
private void toggleTodoVisibility() {
263284
TransitionManager.beginDelayedTransition(binding.getRoot(), new TransitionSet()
264285
.addTransition(new Slide(Gravity.TOP).addTarget(binding.cvShoplist))
@@ -315,6 +336,7 @@ private void deleteAllTodoItems() {
315336
}
316337
todoList.clear();
317338
shopListAdapter.notifyDataSetChanged();
339+
updateShopListCount();
318340
}
319341
}
320342

0 commit comments

Comments
 (0)