Skip to content

Commit

Permalink
🐛 fixed initial address and card addition
Browse files Browse the repository at this point in the history
  • Loading branch information
adeeteya committed Feb 3, 2024
1 parent e649a30 commit c3056ad
Show file tree
Hide file tree
Showing 31 changed files with 489 additions and 457 deletions.
101 changes: 63 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,36 @@
# 🛌 Flutter Furniture App 🪑
# 🛌 Flutter Furniture App (Timberr) 🪑

Timberr is a fully functional Furniture App Clone Developed using Flutter, Supabase and Getx State Management which is based on this [UI Design](https://www.figma.com/file/dTdGEtZoQd2uRZc8qS5xjr/Timberr?node-id=0%3A1).
Timberr is a robust and feature-rich furniture application clone meticulously crafted using Flutter, Supabase, and Getx State Management. This app seamlessly integrates a sophisticated UI design to provide users with an immersive and intuitive furniture shopping experience.

## 🗃️ Database Schema
This app is based on this [UI Design](https://www.figma.com/file/dTdGEtZoQd2uRZc8qS5xjr/Timberr?node-id=0%3A1).

<img src="images/database.png">
## ✨ Key Features:

## 💻 Installation links
- 🔐 Authentication: Timberr ensures a secure and personalized experience with a robust authentication system, allowing users to create accounts, log in securely, and manage their profiles effortlessly.

- [Android App](https://github.com/adityar224/FlutterFurnitureApp/releases/download/1.0.0/timberr-1.0.0.apk)
- [iOS App](https://github.com/adityar224/FlutterFurnitureApp/releases/download/1.0.0/timberr-1.0.0.ipa)
- 🛒 Cart: The app features a fully functional shopping cart, enabling users to add, remove, and manage items with ease. The cart ensures a smooth and efficient checkout process for a seamless shopping journey.

## ✨ Features
- 💖 Favorites: Timberr incorporates a favorites section, allowing users to curate a personalized list of preferred items. This feature enhances user engagement by providing a quick and convenient way to revisit and purchase favored products.

- [x] Authentication
- [x] Cart
- [x] Favorites
- [x] Address
- [x] Search
- [x] Filtering
- [x] Select Color
- [x] Change Quantity
- [x] Payment Methods
- [x] Razorpay Payment Gateway
- [x] Change User Profile Picture
- [x] Change Name/Password and other User Related Settings
- [x] Smooth Animations
- [x] Loading Screens
- [ ] Reviews (Only UI implemented)
- [ ] Orders (Only UI implemented)
- [ ] Notifications (Only UI implemented)
- [ ] Dark Mode
- [ ] Responsive Design
- 🗺️ Address: Users can effortlessly manage their delivery addresses, ensuring a hassle-free and customized shopping experience. The address feature enhances convenience by enabling users to save and update their preferred delivery locations.

- 🔍 Search and Filtering: Timberr integrates a powerful search functionality and advanced filtering options, facilitating users in discovering desired furniture items efficiently.

- 🌈 Select Color: Users can customize their furniture selection by choosing from a variety of colors, adding a touch of personalization to their shopping experience.

- 💳 Payment Methods: The app supports multiple payment methods, ensuring a secure and versatile checkout process for users. This feature includes integration with the Razorpay payment gateway for a seamless and reliable transaction experience.

- 👤 User Profile Management: Timberr empowers users to personalize their profiles by enabling them to change profile pictures, update names, passwords, and other user-related settings, enhancing the overall user experience.

- 💫 Smooth Animations: The app incorporates smooth and visually appealing animations, enhancing the overall user interface and providing a delightful interaction experience.

- 🚧 Reviews, Orders, and Notifications: While currently implemented as UI elements, Timberr sets the foundation for future functionality, allowing users to access and view product reviews, order history, and notifications – enhancing user engagement and information accessibility.

## 💻 Installation links

[![Download Android Apk](https://img.shields.io/badge/Download-Android%20Apk-green)](https://github.com/adityar224/FlutterFurnitureApp/releases/download/2.0.0/timberr-2.0.0.apk)

[![Download iOS ipa](https://img.shields.io/badge/Download-iOS%20App-black)](https://github.com/adityar224/FlutterFurnitureApp/releases/download/1.0.0/timberr-1.0.0.ipa)

## 📸 Screen Recordings

Expand Down Expand Up @@ -93,23 +92,49 @@ Timberr is a fully functional Furniture App Clone Developed using Flutter, Supab
<img alt="Sign out" loading="lazy" src="images/sign_out.gif" height="587px" width="256px"/>
</details><br>

## 🗃️ Database Schema

<img src="images/database.png">

## 🔌 Plugins

|Name|Usage|
|-|-|
|[**get**](https://pub.dev/packages/get)|Dependency injection, State and Route management|
|[**supabase_flutter**](https://pub.dev/packages/supabase_flutter)|Authentication, Database and Storage|
|[**cached_network_image**](https://pub.dev/packages/cached_network_image)|Caching Product and user images|
|[**lottie**](https://pub.dev/packages/lottie)|Loading Animations|
|[**url_launcher**](https://pub.dev/packages/url_launcher)|To open FAQ in a browser|
|[**image_picker**](https://pub.dev/packages/image_picker)|To select user profile picture from their device|
|[**razorpay_flutter**](https://pub.dev/packages/razorpay_flutter)|Payment Gateway through Razorpay|
|[**flutter_lints**](https://pub.dev/packages/flutter_lints)|For linting|
| Name | Usage |
|---------------------------------------------------------------------------|--------------------------------------------------|
| [**get**](https://pub.dev/packages/get) | Dependency injection, State and Route management |
| [**supabase_flutter**](https://pub.dev/packages/supabase_flutter) | Authentication, Database and Storage |
| [**cached_network_image**](https://pub.dev/packages/cached_network_image) | Caching Product and user images |
| [**lottie**](https://pub.dev/packages/lottie) | Loading Animations |
| [**url_launcher**](https://pub.dev/packages/url_launcher) | To open FAQ in a browser |
| [**image_picker**](https://pub.dev/packages/image_picker) | To select user profile picture from their device |
| [**razorpay_flutter**](https://pub.dev/packages/razorpay_flutter) | Payment Gateway through Razorpay |
| [**flutter_lints**](https://pub.dev/packages/flutter_lints) | For linting |

## 📃 Feature Todo List

- [x] Authentication
- [x] Cart
- [x] Favorites
- [x] Address
- [x] Search
- [x] Filtering
- [x] Select Color
- [x] Change Quantity
- [x] Payment Methods
- [x] Razorpay Payment Gateway
- [x] Change User Profile Picture
- [x] Change Name/Password and other User Related Settings
- [x] Smooth Animations
- [x] Loading Screens
- [ ] Reviews (Only UI implemented)
- [ ] Orders (Only UI implemented)
- [ ] Notifications (Only UI implemented)
- [ ] Dark Mode
- [ ] Responsive Design (Only Mobile version implemented)

## 🤓 Author

**[Aditya R](https://github.com/adityar224)**

## 🔖 LICENCE
Copyright (c) 2022 Aditya R
[MIT LICENCE](https://github.com/adityar224/FlutterFurnitureApp/blob/master/LICENSE)
[MIT LICENCE](https://github.com/adityar224/FlutterFurnitureApp/blob/master/LICENSE)
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
## Supported Versions

| Version | Supported |
|---------| ------------------ |
|---------|--------------------|
| 2.0.0 | :white_check_mark: |
| 1.0.0 | :white_check_mark: |

## Reporting a Vulnerability
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.aditya.timberr">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="timberr"
android:name="${applicationName}"
Expand Down
3 changes: 3 additions & 0 deletions assets/icons/cart_icon_grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions assets/icons/favorite_icon_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions assets/icons/logout_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/search_icon_grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions assets/icons/shopping_bag_icon_black.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 9 additions & 11 deletions lib/controllers/add_payment_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,27 @@ class AddPaymentController extends GetxController {
final _supabaseClient = Supabase.instance.client;
final CardDetailsController _cardDetailsController = Get.find();

Future addCardDetail() async {
Future<void> addCardDetail() async {
final insertData = await _supabaseClient.from("Card_Details").insert({
"cardholder_name": name.value,
"card_number": cardNumber,
"month": month,
"year": year,
"user_id": _supabaseClient.auth.user()?.id
}).execute();
"user_id": _supabaseClient.auth.currentUser!.id
}).select();
if (_cardDetailsController.cardDetailList.isEmpty) {
_cardDetailsController.selectedIndex.value = 0;
//set default user Address Id in the database
//set default user Card Id in the database
await _supabaseClient
.from("Users")
.update({'default_card_detail_id': insertData.data[0]})
.eq(
"Uid",
_supabaseClient.auth.user()?.id,
)
.execute();
.update({'default_card_detail_id': insertData[0]['id']}).eq(
"Uid",
_supabaseClient.auth.currentUser!.id,
);
}
_cardDetailsController.cardDetailList.add(
CardDetail(
id: insertData.data[0]['id'],
id: insertData[0]['id'],
name: name.value,
cardNumber: cardNumber,
month: month,
Expand Down
75 changes: 31 additions & 44 deletions lib/controllers/address_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,27 @@ class AddressController extends GetxController {
String name = "", address = "", country = "", city = "", district = "";
int pincode = 0;

Future fetchAddresses() async {
Future<void> fetchAddresses() async {
//get address list
final response = await _supabaseClient
.from("Addresses")
.select()
.eq(
final response = await _supabaseClient.from("Addresses").select().eq(
"user_id",
_supabaseClient.auth.user()?.id,
)
.execute();
final responseList = response.data as List;
_supabaseClient.auth.currentUser!.id,
);
final responseList = response;
for (int i = 0; i < responseList.length; i++) {
addressList.add(Address.fromJson(responseList[i]));
}
update();
}

Future getDefaultShippingAddress() async {
Future<void> getDefaultShippingAddress() async {
//get default shipping address
final defaultShippingResponse = await _supabaseClient
.from("Users")
.select('default_shipping_id')
.eq(
"Uid",
_supabaseClient.auth.user()?.id,
)
.execute();
int? responseId = defaultShippingResponse.data[0]['default_shipping_id'];
final defaultShippingResponse =
await _supabaseClient.from("Users").select('default_shipping_id').eq(
"Uid",
_supabaseClient.auth.currentUser!.id,
);
int? responseId = defaultShippingResponse[0]['default_shipping_id'];
await fetchAddresses();
if (responseId != null) {
for (int i = 0; i < addressList.length; i++) {
Expand All @@ -51,48 +44,44 @@ class AddressController extends GetxController {
}
}

Future setDefaultShippingAddress(int index) async {
Future<void> setDefaultShippingAddress(int index) async {
if (selectedIndex == index) {
return;
}
selectedIndex = index;
update();
await _supabaseClient
.from("Users")
.update({'default_shipping_id': addressList.elementAt(index).id})
.eq(
"Uid",
_supabaseClient.auth.user()?.id,
)
.execute();
.update({'default_shipping_id': addressList.elementAt(index).id}).eq(
"Uid",
_supabaseClient.auth.currentUser!.id,
);
}

Future uploadAddress() async {
Future<void> uploadAddress() async {
final insertData = await _supabaseClient.from("Addresses").insert({
'full_name': name,
'address': address,
'pincode': pincode,
'country': country,
'city': city,
'district': district,
'user_id': _supabaseClient.auth.user()?.id,
}).execute();
'user_id': _supabaseClient.auth.currentUser!.id,
}).select();
if (addressList.isEmpty) {
selectedIndex = 0;
//set default user Address Id in the database
await _supabaseClient
.from("Users")
.update({'default_shipping_id': insertData.data[0]})
.eq(
"Uid",
_supabaseClient.auth.user()?.id,
)
.execute();
.update({'default_shipping_id': insertData[0]['id']}).eq(
"Uid",
_supabaseClient.auth.currentUser!.id,
);
}
//add to shipping address list
addressList.add(
Address(
id: insertData.data[0]['id'],
id: insertData[0]['id'],
name: name,
address: address,
pincode: pincode,
Expand All @@ -105,7 +94,7 @@ class AddressController extends GetxController {
Get.back();
}

Future editAddress(int index, int addressId) async {
Future<void> editAddress(int index, int addressId) async {
Address newAddress = Address(
id: addressId,
name: name,
Expand All @@ -118,15 +107,14 @@ class AddressController extends GetxController {
await _supabaseClient
.from("Addresses")
.update(newAddress.toJson())
.eq("id", addressId)
.execute();
.eq("id", addressId);
//update the value locally
addressList[index] = newAddress;
update();
Get.back();
}

Future deleteAddress(int index) async {
Future<void> deleteAddress(int index) async {
//check if it is the selected index
if (index == selectedIndex) {
if (addressList.length == 1) {
Expand All @@ -135,15 +123,14 @@ class AddressController extends GetxController {
return;
} else {
selectedIndex = 0;
setDefaultShippingAddress((index == 0) ? 1 : 0);
await setDefaultShippingAddress((index == 0) ? 1 : 0);
}
}
//remove address from the database
await _supabaseClient
.from("Addresses")
.delete(returning: ReturningOption.minimal)
.eq("id", addressList.elementAt(index).id)
.execute();
.delete()
.eq("id", addressList.elementAt(index).id);
//remove from local list
addressList.removeAt(index);
//go back to previous page
Expand Down
Loading

0 comments on commit c3056ad

Please sign in to comment.