From 6b842febe8c2d9d23f4c19e0c6616244b1122a7a Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Thu, 17 Oct 2024 02:03:14 -0600 Subject: [PATCH 1/9] se crearon las tablas de la base de datos --- lib/database/database.dart | 151 ++++++++++++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 130 ++++++++++++++- pubspec.yaml | 2 + 4 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 lib/database/database.dart diff --git a/lib/database/database.dart b/lib/database/database.dart new file mode 100644 index 0000000..5c1d7af --- /dev/null +++ b/lib/database/database.dart @@ -0,0 +1,151 @@ +import 'dart:io'; +import 'package:path_provider/path_provider.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:path/path.dart'; + +class MoviesDatabase { + static final NAMEDB = 'PizzeriaDB'; + static final VERSIONDB = 1; + + static Database? _database; + + Future get database async { + if (_database != null) return _database!; + return _database = await initDatabase(); + } + + Future initDatabase() async { + Directory folder = await getApplicationDocumentsDirectory(); + String path = join(folder.path, NAMEDB); + return openDatabase( + path, + version: VERSIONDB, + onCreate: (db, version) { + String query1 = ''' + CREATE TABLE categoria( + id_categoria INTEGER PRIMARY KEY, + categoria VARCHAR(100) + ); + '''; + + db.execute(query1); + + String query2 = ''' + CREATE TABLE producto( + id_producto INTEGER PRIMARY KEY, + producto VARCHAR(100), + precio NUMERIC, + descripcion VARCHAR(300), + id_categoria INT, + img_producto VARCHAR(150), + CONSTRAINT Producto_categoria_fk FOREIGN KEY(id_categoria) REFERENCES categoria(id_categoria) + );'''; + db.execute(query2); + + String query3 = ''' + CREATE TABLE carrito( + id_carrito INTEGER PRIMARY KEY, + id_producto INT, + cantidad INT, + subtotal NUMERIC, + CONSTRAINT carrito_producto_fk FOREIGN KEY(id_producto) REFERENCES producto(id_producto) + );'''; + db.execute(query3); + + String query4 = ''' + CREATE TABLE status( + id_status INTEGER PRIMARY KEY, + status VARCHAR(50) + );'''; + db.execute(query4); + String query5 = ''' + CREATE TABLE municipio( + id_municipio INTEGER PRIMARY KEY, + municipio varchar(150) + );'''; + db.execute(query5); + String query6 = ''' + CREATE TABLE comunidad( + id_comunidad INTEGER PRIMARY KEY, + id_municipio INT, + comunidad VARCHAR(150), + CONSTRAINT comunidad_municipio_fk FOREIGN KEY(id_municipio) REFERENCES municipio(id_municipio) + );'''; + db.execute(query6); + String query7 = ''' + CREATE TABLE direccion( + id_direccion INTEGER PRIMARY KEY, + id_comunidad INT, + calle VARCHAR(150) not null, + colonia VARCHAR(150), + no_exterior INT not null, + no_interior INT, + num_telefono VARCHAR(18), + nombre_cliente VARCHAR(100) not null, + CONSTRAINT direccion_comunidad_fk FOREIGN KEY(id_comunidad) REFERENCES comunidad(id_comunidad) + );'''; + db.execute(query7); + String query8 = ''' + CREATE TABLE pedido( + id_pedido INTEGER PRIMARY KEY, + id_status INT, + id_direccion INT, + fecha_entrega TEXT, + CONSTRAINT pedido_status_fk FOREIGN KEY(id_status) REFERENCES status(id_status), + CONSTRAINT pedido_direccion_fk FOREIGN KEY(id_direccion) REFERENCES direccion(id_direccion) + );'''; + db.execute(query8); + String query9 = ''' + CREATE TABLE lista_pedido( + id_lista_pedido INTEGER PRIMARY KEY, + id_producto INT, + cantidad INT, + subtotal NUMERIC, + CONSTRAINT listaPedido_producto_fk FOREIGN KEY(id_producto) REFERENCES producto(id_producto) + );'''; + db.execute(query9); + }, + ); + } // initdatabase + + Future INSERT(String table, Map row) async { + var con = await database; + return await con.insert(table, row); + } + + Future UPDATE(String table, Map row) async { + var con = await database; + return await con + .update(table, row, where: 'idMovie = ?', whereArgs: [row['idMovie']]); + } + + Future DELETE(String table, int idMovie) async { + var con = await database; + return await con.delete(table, where: 'idMovie = ?', whereArgs: [idMovie]); + } + + // Future?> SELECT() async { + // var con = await database; + // var result = await con.query('tblmovies'); + // return result.map((movie) => MoviesDAO.fromMap(movie)).toList(); + // } +} + +/* CREATE TABLE tblmovies( + idMovie INTEGER PRIMARY KEY, + nameMovie VARCHAR(100), + overview TEXT, + idGenre char(1), + imgMovie VARCHAR(150), + releaseDate CHAR(10), + CONSTRAINT fk_gen FOREIGN KEY(idGenre) REFERENCES tblgenre(idGenre) + +CONSTRAINT fk_gen FOREIGN KEY(idGenre) REFERENCES tblgenre(idGenre) + + CREATE TABLE tblgenre( + idGenre char(1) PRIMARY KEY, + dscgenre VARCHAR(50) + ); + + + );*/ \ No newline at end of file diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cccf817..29d4e7f 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,6 +5,8 @@ import FlutterMacOS import Foundation +import sqflite_darwin func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index af2ac16..3025d92 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" flutter: dependency: "direct main" description: flutter @@ -139,6 +147,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + url: "https://pub.dev" + source: hosted + version: "2.2.12" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" sky_engine: dependency: transitive description: flutter @@ -152,6 +224,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" + url: "https://pub.dev" + source: hosted + version: "2.5.4+5" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027" + url: "https://pub.dev" + source: hosted + version: "2.4.1-1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" stack_trace: dependency: transitive description: @@ -176,6 +288,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -208,6 +328,14 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.4" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" sdks: dart: ">=3.5.0 <4.0.0" - flutter: ">=3.18.0-18.0.pre.54" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index f29cbd6..5ebcc6d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,8 @@ environment: dependencies: flutter: sdk: flutter + sqflite: ^2.3.3+1 + path_provider: ^2.1.4 # The following adds the Cupertino Icons font to your application. From 86c370d84757a11c7cb4880d9365e5109b8826a2 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Thu, 17 Oct 2024 02:56:34 -0600 Subject: [PATCH 2/9] se creo el modelo de categoria y se mando a mostrar al menu de la app, si funciono --- lib/database/database.dart | 43 ++++++------- lib/main.dart | 11 +++- lib/models/categoria_model.dart | 14 +++++ lib/screens/MenuAppResponsiveScreen.dart | 23 +++++++ lib/screens/menuApp/MenuApp_screenH.dart | 20 +++++++ lib/screens/menuApp/MenuApp_screenV.dart | 60 +++++++++++++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + 7 files changed, 145 insertions(+), 28 deletions(-) create mode 100644 lib/models/categoria_model.dart create mode 100644 lib/screens/MenuAppResponsiveScreen.dart create mode 100644 lib/screens/menuApp/MenuApp_screenH.dart create mode 100644 lib/screens/menuApp/MenuApp_screenV.dart diff --git a/lib/database/database.dart b/lib/database/database.dart index 5c1d7af..a5b8766 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -2,8 +2,9 @@ import 'dart:io'; import 'package:path_provider/path_provider.dart'; import 'package:sqflite/sqflite.dart'; import 'package:path/path.dart'; +import 'package:store_sqlite/models/categoria_model.dart'; -class MoviesDatabase { +class TiendaDataBase { static final NAMEDB = 'PizzeriaDB'; static final VERSIONDB = 1; @@ -104,6 +105,16 @@ class MoviesDatabase { CONSTRAINT listaPedido_producto_fk FOREIGN KEY(id_producto) REFERENCES producto(id_producto) );'''; db.execute(query9); + String query10 = ''' + INSERT INTO categoria + (categoria) + VALUES + ('Pizza'), + ('Refreco'), + ('Agua') + ; +'''; + db.execute(query10); }, ); } // initdatabase @@ -124,28 +135,10 @@ class MoviesDatabase { return await con.delete(table, where: 'idMovie = ?', whereArgs: [idMovie]); } - // Future?> SELECT() async { - // var con = await database; - // var result = await con.query('tblmovies'); - // return result.map((movie) => MoviesDAO.fromMap(movie)).toList(); - // } -} - -/* CREATE TABLE tblmovies( - idMovie INTEGER PRIMARY KEY, - nameMovie VARCHAR(100), - overview TEXT, - idGenre char(1), - imgMovie VARCHAR(150), - releaseDate CHAR(10), - CONSTRAINT fk_gen FOREIGN KEY(idGenre) REFERENCES tblgenre(idGenre) - -CONSTRAINT fk_gen FOREIGN KEY(idGenre) REFERENCES tblgenre(idGenre) + Future?> SELECT() async { + var con = await database; + var result = await con.query('categoria'); + return result.map((categoria)=>CategoriaModel.fromMap(categoria)).toList(); + } - CREATE TABLE tblgenre( - idGenre char(1) PRIMARY KEY, - dscgenre VARCHAR(50) - ); - - - );*/ \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 1aee164..2baa9d4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:store_sqlite/routes/rutes.dart'; +import 'package:store_sqlite/screens/MenuAppResponsiveScreen.dart'; import 'package:store_sqlite/screens/login/login_ScreenH.dart'; import 'package:store_sqlite/screens/login/login_screenV.dart'; import 'package:store_sqlite/screens/loginResponsiveScreen.dart'; +import 'package:store_sqlite/screens/menuApp/MenuApp_screenH.dart'; +import 'package:store_sqlite/screens/menuApp/MenuApp_screenV.dart'; void main() => runApp(const MyApp()); @@ -13,9 +16,11 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: 'Material App', - home: const loginResponsiveScreen( - pantallaVerticalMobile: LoginScreenVertical(), - pantallaHorizontalMobile: LoginScreenHorizontal()), + debugShowCheckedModeBanner: false, + theme: ThemeData.dark(), + home: const Menuappresponsivescreen( + pantallaVerticalMobile: MenuappScreenv(), + pantallaHorizontalMobile: MenuappScreenH()), routes: AppRoutes.routes, ); } diff --git a/lib/models/categoria_model.dart b/lib/models/categoria_model.dart new file mode 100644 index 0000000..6ed5f25 --- /dev/null +++ b/lib/models/categoria_model.dart @@ -0,0 +1,14 @@ +class CategoriaModel { + int? id_categoria; + String? categoria; + + CategoriaModel({this.id_categoria, this.categoria}); + + factory CategoriaModel.fromMap(Map categoria){ + return CategoriaModel( + //idGenre: movie['idGenre'], + id_categoria: categoria['id_categoria'], + categoria: categoria['categoria'] + ); + } +} diff --git a/lib/screens/MenuAppResponsiveScreen.dart b/lib/screens/MenuAppResponsiveScreen.dart new file mode 100644 index 0000000..c7141cc --- /dev/null +++ b/lib/screens/MenuAppResponsiveScreen.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; + +class Menuappresponsivescreen extends StatelessWidget { + const Menuappresponsivescreen( + {super.key, + required this.pantallaVerticalMobile, + required this.pantallaHorizontalMobile}); + + final Widget pantallaVerticalMobile; + final Widget pantallaHorizontalMobile; + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + if (constraints.maxWidth < 600) { + return pantallaVerticalMobile; + } else { + return pantallaHorizontalMobile; + } + }, + ); + } +} diff --git a/lib/screens/menuApp/MenuApp_screenH.dart b/lib/screens/menuApp/MenuApp_screenH.dart new file mode 100644 index 0000000..37ad4b0 --- /dev/null +++ b/lib/screens/menuApp/MenuApp_screenH.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +class MenuappScreenH extends StatefulWidget { + const MenuappScreenH({super.key}); + + @override + State createState() => _MenuappScreenvState(); +} + +class _MenuappScreenvState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Menu App'), + ), + body: Text('menu app'), + ); + } +} diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart new file mode 100644 index 0000000..55ad063 --- /dev/null +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -0,0 +1,60 @@ +import 'package:flutter/material.dart'; +import 'package:sqflite/sqflite.dart'; +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/categoria_model.dart'; + +class MenuappScreenv extends StatefulWidget { + const MenuappScreenv({super.key}); + + @override + State createState() => _MenuappScreenvState(); +} + +class _MenuappScreenvState extends State { + late TiendaDataBase categoriaDB; + + @override + void initState() { + super.initState(); + categoriaDB = TiendaDataBase(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Menu App'), + actions: [ + IconButton( + onPressed: () {}, + icon: Icon(Icons.add), + ), + ], + backgroundColor: const Color.fromARGB(131, 50, 45, 45), + ), + body: FutureBuilder( + future: categoriaDB.SELECT(), + builder: (context, AsyncSnapshot?> snapshot) { + if (snapshot.hasData) { + return ListView.builder( + itemCount: snapshot.data!.length, + itemBuilder: (context, index) { + return Text( + 'los valores del snapshot= ${snapshot.data![index].categoria}'); + //MovieViewItem(moviesDAO: snapshot.data![index],); + }, + ); + } else { + if (snapshot.hasError) { + return Center( + child: Text(snapshot.error.toString()), + ); + } else { + return Center( + child: CircularProgressIndicator(), + ); + } + } + })); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 29d4e7f..252c004 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,8 +5,10 @@ import FlutterMacOS import Foundation +import path_provider_foundation import sqflite_darwin func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } From ce69e82f1eca43863ad51463dea0d058e1c20588 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Thu, 17 Oct 2024 15:01:08 -0600 Subject: [PATCH 3/9] creacion de modelos y controladores --- lib/controller/Comunidad_controller.dart | 28 +++++++++++++++++ lib/controller/carrito_controller.dart | 29 +++++++++++++++++ lib/controller/categoria_controller.dart | 30 ++++++++++++++++++ lib/controller/direccion_controller.dart | 28 +++++++++++++++++ lib/controller/listaPedido_controller.dart | 28 +++++++++++++++++ lib/controller/municipio_controller.dart | 29 +++++++++++++++++ lib/controller/pedido_controller.dart | 28 +++++++++++++++++ lib/controller/producto_controller.dart | 29 +++++++++++++++++ lib/controller/status_controller.dart | 28 +++++++++++++++++ lib/database/database.dart | 36 +++++++++++----------- lib/models/carrito_model.dart | 15 +++++++++ lib/models/comunidad_model.dart | 12 ++++++++ lib/models/direccion_model.dart | 28 +++++++++++++++++ lib/models/lista_pedido_model.dart | 14 +++++++++ lib/models/municipio_model.dart | 11 +++++++ lib/models/pedido_model.dart | 15 +++++++++ lib/models/producto_model.dart | 26 ++++++++++++++++ lib/models/status_model.dart | 10 ++++++ lib/screens/menuApp/MenuApp_screenV.dart | 7 +++-- 19 files changed, 410 insertions(+), 21 deletions(-) create mode 100644 lib/controller/Comunidad_controller.dart create mode 100644 lib/controller/carrito_controller.dart create mode 100644 lib/controller/categoria_controller.dart create mode 100644 lib/controller/direccion_controller.dart create mode 100644 lib/controller/listaPedido_controller.dart create mode 100644 lib/controller/municipio_controller.dart create mode 100644 lib/controller/pedido_controller.dart create mode 100644 lib/controller/producto_controller.dart create mode 100644 lib/controller/status_controller.dart create mode 100644 lib/models/carrito_model.dart create mode 100644 lib/models/comunidad_model.dart create mode 100644 lib/models/direccion_model.dart create mode 100644 lib/models/lista_pedido_model.dart create mode 100644 lib/models/municipio_model.dart create mode 100644 lib/models/pedido_model.dart create mode 100644 lib/models/producto_model.dart create mode 100644 lib/models/status_model.dart diff --git a/lib/controller/Comunidad_controller.dart b/lib/controller/Comunidad_controller.dart new file mode 100644 index 0000000..a57f6da --- /dev/null +++ b/lib/controller/Comunidad_controller.dart @@ -0,0 +1,28 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/comunidad_model.dart'; + +class ComunidadController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertarComunidad(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodasLasComunidades() async { + var con = await _dataBase.database; + var result = await con.query('comunidad'); + return result.map((comunidad)=>ComunidadModel.fromMap(comunidad)).toList(); + } + + Future actualizarComunidad(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_comunidad = ?', whereArgs: [row['id_comunidad']]); + } + Future eliminarComunidad(String table, int id_comunidad) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_comunidad = ?', whereArgs: [id_comunidad]); + } + +} \ No newline at end of file diff --git a/lib/controller/carrito_controller.dart b/lib/controller/carrito_controller.dart new file mode 100644 index 0000000..c589a15 --- /dev/null +++ b/lib/controller/carrito_controller.dart @@ -0,0 +1,29 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/carrito_model.dart'; + +class CarritoController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertCarrito(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarCarritos() async { + var con = await _dataBase.database; + var result = await con.query('id_carrito'); + return result.map((carrito) => CarritoModel.fromMap(carrito)).toList(); + } + + Future actualizarCarrito(String table, Map row) async { + var con = await _dataBase.database; + return await con.update(table, row, + where: 'id_carrito = ?', whereArgs: [row['id_carrito']]); + } + + Future eliminarCarrito(String table, int id_carrito) async { + var con = await _dataBase.database; + return await con + .delete(table, where: 'id_carrito = ?', whereArgs: [id_carrito]); + } +} diff --git a/lib/controller/categoria_controller.dart b/lib/controller/categoria_controller.dart new file mode 100644 index 0000000..d5d1785 --- /dev/null +++ b/lib/controller/categoria_controller.dart @@ -0,0 +1,30 @@ +import 'package:sqflite/sqflite.dart'; +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/categoria_model.dart'; + +class CategoriaController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertCategoria(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodasLasCategorias() async { + var con = await _dataBase.database; + var result = await con.query('categoria'); + return result.map((categoria)=>CategoriaModel.fromMap(categoria)).toList(); + } + + Future actualizarCategoria(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_categoria = ?', whereArgs: [row['id_categoria']]); + } + Future eliminarCategoria(String table, int id_categoria) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_categoria = ?', whereArgs: [id_categoria]); + } + + // Métodos adicionales como update, delete, etc. +} diff --git a/lib/controller/direccion_controller.dart b/lib/controller/direccion_controller.dart new file mode 100644 index 0000000..1ea4591 --- /dev/null +++ b/lib/controller/direccion_controller.dart @@ -0,0 +1,28 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/direccion_model.dart'; + +class DireccionController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertCategoria(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodasLasDirecciones() async { + var con = await _dataBase.database; + var result = await con.query('categoria'); + return result.map((direccion)=>DireccionModel.fromMap(direccion)).toList(); + } + + Future actualizarDireccion(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_direccion = ?', whereArgs: [row['id_direccion']]); + } + Future eliminarDireccion(String table, int id_direccion) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_direccion = ?', whereArgs: [id_direccion]); + } + +} \ No newline at end of file diff --git a/lib/controller/listaPedido_controller.dart b/lib/controller/listaPedido_controller.dart new file mode 100644 index 0000000..77d9e17 --- /dev/null +++ b/lib/controller/listaPedido_controller.dart @@ -0,0 +1,28 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/lista_pedido_model.dart'; + +class ListapedidoController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertarListaPedido(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodasLasCategorias() async { + var con = await _dataBase.database; + var result = await con.query('lista_pedido'); + return result.map((lista_pedido)=>ListaPedidoModel.fromMap(lista_pedido)).toList(); + } + + Future actualizarListaPedido(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_lista_pedido = ?', whereArgs: [row['id_lista_pedido']]); + } + Future eliminarListaPedido(String table, int id_lista_pedido) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_lista_pedido = ?', whereArgs: [id_lista_pedido]); + } + +} \ No newline at end of file diff --git a/lib/controller/municipio_controller.dart b/lib/controller/municipio_controller.dart new file mode 100644 index 0000000..7df0f30 --- /dev/null +++ b/lib/controller/municipio_controller.dart @@ -0,0 +1,29 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/municipio_model.dart'; + +class MunicipioController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertarMunicipio(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodosLosMunicipios() async { + var con = await _dataBase.database; + var result = await con.query('municipio'); + return result.map((municipio)=>MunicipioModel.fromMap(municipio)).toList(); + } + + Future actualizarMunicipio(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_municipio = ?', whereArgs: [row['id_municipio']]); + } + Future eliminarMunicipio(String table, int id_municipio) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_municipio = ?', whereArgs: [id_municipio]); + } + + +} \ No newline at end of file diff --git a/lib/controller/pedido_controller.dart b/lib/controller/pedido_controller.dart new file mode 100644 index 0000000..48eacec --- /dev/null +++ b/lib/controller/pedido_controller.dart @@ -0,0 +1,28 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/pedido_model.dart'; + +class PedidoController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertarPedido(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodosLosPedidos() async { + var con = await _dataBase.database; + var result = await con.query('pedido'); + return result.map((pedido)=>PedidoModel.fromMap(pedido)).toList(); + } + + Future actualizarPedido(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_pedido = ?', whereArgs: [row['id_pedido']]); + } + Future eliminarPedido(String table, int id_pedido) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_pedido = ?', whereArgs: [id_pedido]); + } + +} \ No newline at end of file diff --git a/lib/controller/producto_controller.dart b/lib/controller/producto_controller.dart new file mode 100644 index 0000000..8b942b5 --- /dev/null +++ b/lib/controller/producto_controller.dart @@ -0,0 +1,29 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/producto_model.dart'; + +class ProductoController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertProducto(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodosLosProductos() async { + var con = await _dataBase.database; + var result = await con.query('producto'); + return result.map((producto) => ProductoModel.fromMap(producto)).toList(); + } + + Future actualizarProducto(String table, Map row) async { + var con = await _dataBase.database; + return await con.update(table, row, + where: 'id_producto = ?', whereArgs: [row['id_producto']]); + } + + Future eliminarProducto(String table, int id_producto) async { + var con = await _dataBase.database; + return await con + .delete(table, where: 'id_producto = ?', whereArgs: [id_producto]); + } +} diff --git a/lib/controller/status_controller.dart b/lib/controller/status_controller.dart new file mode 100644 index 0000000..41b126c --- /dev/null +++ b/lib/controller/status_controller.dart @@ -0,0 +1,28 @@ +import 'package:store_sqlite/database/database.dart'; +import 'package:store_sqlite/models/status_model.dart'; + +class StatusController { + final TiendaDataBase _dataBase = TiendaDataBase(); + + Future insertarNuevoStatus(String table, Map row) async { + final db = await _dataBase.database; + return await db.insert(table, row); + } + + Future?> mostrarTodosLosStatus() async { + var con = await _dataBase.database; + var result = await con.query('status'); + return result.map((status)=>StatusModel.fromMap(status)).toList(); + } + + Future actualizarStatus(String table, Map row) async { + var con = await _dataBase.database; + return await con + .update(table, row, where: 'id_status = ?', whereArgs: [row['id_status']]); + } + Future eliminarStatus(String table, int id_status) async { + var con = await _dataBase.database; + return await con.delete(table, where: 'id_status = ?', whereArgs: [id_status]); + } + +} \ No newline at end of file diff --git a/lib/database/database.dart b/lib/database/database.dart index a5b8766..b4244ce 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -119,26 +119,26 @@ class TiendaDataBase { ); } // initdatabase - Future INSERT(String table, Map row) async { - var con = await database; - return await con.insert(table, row); - } + // Future INSERT(String table, Map row) async { + // var con = await database; + // return await con.insert(table, row); + // } - Future UPDATE(String table, Map row) async { - var con = await database; - return await con - .update(table, row, where: 'idMovie = ?', whereArgs: [row['idMovie']]); - } + // Future UPDATE(String table, Map row) async { + // var con = await database; + // return await con + // .update(table, row, where: 'idMovie = ?', whereArgs: [row['idMovie']]); + // } - Future DELETE(String table, int idMovie) async { - var con = await database; - return await con.delete(table, where: 'idMovie = ?', whereArgs: [idMovie]); - } + // Future DELETE(String table, int idMovie) async { + // var con = await database; + // return await con.delete(table, where: 'idMovie = ?', whereArgs: [idMovie]); + // } - Future?> SELECT() async { - var con = await database; - var result = await con.query('categoria'); - return result.map((categoria)=>CategoriaModel.fromMap(categoria)).toList(); - } + // Future?> SELECT() async { + // var con = await database; + // var result = await con.query('categoria'); + // return result.map((categoria)=>CategoriaModel.fromMap(categoria)).toList(); + // } } diff --git a/lib/models/carrito_model.dart b/lib/models/carrito_model.dart new file mode 100644 index 0000000..fe4c190 --- /dev/null +++ b/lib/models/carrito_model.dart @@ -0,0 +1,15 @@ +class CarritoModel { + int? id_carrito; + int? id_producto; + int? cantidad; + double? subtotal; + CarritoModel( + {this.id_carrito, this.id_producto, this.cantidad, this.subtotal}); + factory CarritoModel.fromMap(Map carrito) { + return CarritoModel( + id_carrito: carrito['id_carrito'], + id_producto: carrito['id_producto'], + cantidad: carrito['cantidad'], + subtotal: carrito['subtotal']); + } +} diff --git a/lib/models/comunidad_model.dart b/lib/models/comunidad_model.dart new file mode 100644 index 0000000..4834ec7 --- /dev/null +++ b/lib/models/comunidad_model.dart @@ -0,0 +1,12 @@ +class ComunidadModel { + int? id_comunidad, id_municipio; + String? comunidad; + ComunidadModel({this.id_comunidad, this.id_municipio, this.comunidad}); + + factory ComunidadModel.fromMap(Map comunidad) { + return ComunidadModel( + id_comunidad: comunidad['id_comunidad'], + id_municipio: comunidad['id_municipio'], + comunidad: comunidad['comunidad']); + } +} diff --git a/lib/models/direccion_model.dart b/lib/models/direccion_model.dart new file mode 100644 index 0000000..97593d5 --- /dev/null +++ b/lib/models/direccion_model.dart @@ -0,0 +1,28 @@ +class DireccionModel { + int? id_direccion; + int? id_comunidad, no_exterior, no_interior; + String? calle; + String? colonia, num_telefono, nombre_cliente; + + DireccionModel( + {this.id_direccion, + this.id_comunidad, + this.calle, + this.colonia, + this.no_exterior, + this.no_interior, + this.num_telefono, + this.nombre_cliente}); + + factory DireccionModel.fromMap(Map direccion) { + return DireccionModel( + id_direccion: direccion['id_direccion'], + id_comunidad: direccion['id_comunidad'], + calle: direccion['calle'], + colonia: direccion['colonia'], + no_exterior: direccion['no_exterior'], + no_interior: direccion['no_interior'], + num_telefono: direccion['num_telefono'], + nombre_cliente: direccion['nombre_cliente']); + } +} diff --git a/lib/models/lista_pedido_model.dart b/lib/models/lista_pedido_model.dart new file mode 100644 index 0000000..972e296 --- /dev/null +++ b/lib/models/lista_pedido_model.dart @@ -0,0 +1,14 @@ +class ListaPedidoModel { + int? id_lista_pedido, id_producto, cantidad; + double? subtotal; + + ListaPedidoModel( + {this.id_lista_pedido, this.id_producto, this.cantidad, this.subtotal}); + factory ListaPedidoModel.fromMap(Map lista_pedido) { + return ListaPedidoModel( + id_lista_pedido: lista_pedido['id_lista_pedido'], + id_producto: lista_pedido['id_producto'], + cantidad: lista_pedido['cantidad'], + subtotal: lista_pedido['subtotal']); + } +} diff --git a/lib/models/municipio_model.dart b/lib/models/municipio_model.dart new file mode 100644 index 0000000..5470cec --- /dev/null +++ b/lib/models/municipio_model.dart @@ -0,0 +1,11 @@ +class MunicipioModel { + int? id_municipio; + String? municipio; + + MunicipioModel({this.id_municipio, this.municipio}); + factory MunicipioModel.fromMap(Map municipio) { + return MunicipioModel( + id_municipio: municipio['id_municipio'], + municipio: municipio['municipio']); + } +} diff --git a/lib/models/pedido_model.dart b/lib/models/pedido_model.dart new file mode 100644 index 0000000..0ec2be2 --- /dev/null +++ b/lib/models/pedido_model.dart @@ -0,0 +1,15 @@ +class PedidoModel { + int? id_pedido, id_status, id_direccion; + String? fecha_entrega; + + PedidoModel( + {this.id_pedido, this.id_status, this.id_direccion, this.fecha_entrega}); + + factory PedidoModel.fromMap(Map pedido) { + return PedidoModel( + id_pedido: pedido['id_pedido'], + id_status: pedido['id_status'], + id_direccion: pedido['id_direccion'], + fecha_entrega: pedido['fecha_entrega']); + } +} diff --git a/lib/models/producto_model.dart b/lib/models/producto_model.dart new file mode 100644 index 0000000..ea86c1a --- /dev/null +++ b/lib/models/producto_model.dart @@ -0,0 +1,26 @@ + +class ProductoModel { + int? id_producto; + String? producto; + double? precio; + String? descripcion; + int? id_categoria; + String? img_producto; + + ProductoModel( + {this.id_producto, + this.producto, + this.precio, + this.descripcion, + this.id_categoria, + this.img_producto}); + factory ProductoModel.fromMap(Map producto) { + return ProductoModel( + id_producto: producto['id_producto'], + producto: producto['producto'], + precio: producto['precio'], + descripcion: producto['descripcion'], + id_categoria: producto['id_categoria'], + img_producto: producto['img_producto']); + } +} diff --git a/lib/models/status_model.dart b/lib/models/status_model.dart new file mode 100644 index 0000000..670d64e --- /dev/null +++ b/lib/models/status_model.dart @@ -0,0 +1,10 @@ +class StatusModel { + int? id_status; + String? status; + StatusModel({this.id_status, this.status}); + + factory StatusModel.fromMap(Map status) { + return StatusModel( + id_status: status['id_status'], status: status['status']); + } +} diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index 55ad063..8543b34 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:sqflite/sqflite.dart'; +import 'package:store_sqlite/controller/categoria_controller.dart'; import 'package:store_sqlite/database/database.dart'; import 'package:store_sqlite/models/categoria_model.dart'; @@ -12,11 +13,11 @@ class MenuappScreenv extends StatefulWidget { class _MenuappScreenvState extends State { late TiendaDataBase categoriaDB; - + late CategoriaController categoriaController; @override void initState() { super.initState(); - categoriaDB = TiendaDataBase(); + categoriaController = CategoriaController(); } @override @@ -33,7 +34,7 @@ class _MenuappScreenvState extends State { backgroundColor: const Color.fromARGB(131, 50, 45, 45), ), body: FutureBuilder( - future: categoriaDB.SELECT(), + future: categoriaController.mostrarTodasLasCategorias(), builder: (context, AsyncSnapshot?> snapshot) { if (snapshot.hasData) { return ListView.builder( From a297c49ea31fc28bb1cfae7c5c8e6053cec5f7a6 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Fri, 18 Oct 2024 01:39:23 -0600 Subject: [PATCH 4/9] modelos, controlladores basicos han sido creados, la vista principal ya trae los pedidos,el pedido redirige a los datos del pedido, en datos del pedido muestra todo y tiene un boton flotante de opciones --- lib/controller/listaPedido_controller.dart | 2 +- lib/controller/pedido_controller.dart | 70 ++++++++- lib/database/database.dart | 54 ++++++- lib/main.dart | 3 - lib/models/producto_model.dart | 4 +- lib/routes/rutes.dart | 6 +- lib/screens/informacionPedido.dart | 40 ++++++ .../InformacionPedidoWidget.dart | 64 +++++++++ .../floatingButtonWidget.dart | 50 +++++++ .../informacionClienteWidget.dart | 82 +++++++++++ lib/screens/menuApp/MenuApp_screenV.dart | 82 ++++++----- .../widgetMenuApp/PedidosListaWidget.dart | 134 ++++++++++++++++++ pubspec.lock | 24 ++++ pubspec.yaml | 3 + 14 files changed, 562 insertions(+), 56 deletions(-) create mode 100644 lib/screens/informacionPedido.dart create mode 100644 lib/screens/infromacionPedido/InformacionPedidoWidget.dart create mode 100644 lib/screens/infromacionPedido/floatingButtonWidget.dart create mode 100644 lib/screens/infromacionPedido/informacionClienteWidget.dart create mode 100644 lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart diff --git a/lib/controller/listaPedido_controller.dart b/lib/controller/listaPedido_controller.dart index 77d9e17..e48b6a0 100644 --- a/lib/controller/listaPedido_controller.dart +++ b/lib/controller/listaPedido_controller.dart @@ -9,7 +9,7 @@ class ListapedidoController { return await db.insert(table, row); } - Future?> mostrarTodasLasCategorias() async { + Future?> mostrarTodosLosListaPedidos() async { var con = await _dataBase.database; var result = await con.query('lista_pedido'); return result.map((lista_pedido)=>ListaPedidoModel.fromMap(lista_pedido)).toList(); diff --git a/lib/controller/pedido_controller.dart b/lib/controller/pedido_controller.dart index 48eacec..3571002 100644 --- a/lib/controller/pedido_controller.dart +++ b/lib/controller/pedido_controller.dart @@ -2,7 +2,7 @@ import 'package:store_sqlite/database/database.dart'; import 'package:store_sqlite/models/pedido_model.dart'; class PedidoController { - final TiendaDataBase _dataBase = TiendaDataBase(); + final TiendaDataBase _dataBase = TiendaDataBase(); Future insertarPedido(String table, Map row) async { final db = await _dataBase.database; @@ -12,17 +12,73 @@ class PedidoController { Future?> mostrarTodosLosPedidos() async { var con = await _dataBase.database; var result = await con.query('pedido'); - return result.map((pedido)=>PedidoModel.fromMap(pedido)).toList(); + return result.map((pedido) => PedidoModel.fromMap(pedido)).toList(); } - Future actualizarPedido(String table, Map row) async { + Future actualizarPedido(String table, Map row) async { + var con = await _dataBase.database; + return await con.update(table, row, + where: 'id_pedido = ?', whereArgs: [row['id_pedido']]); + } + + Future eliminarPedido(String table, int id_pedido) async { var con = await _dataBase.database; return await con - .update(table, row, where: 'id_pedido = ?', whereArgs: [row['id_pedido']]); + .delete(table, where: 'id_pedido = ?', whereArgs: [id_pedido]); } - Future eliminarPedido(String table, int id_pedido) async { + + Future>?> mostrarPedidosConListaPedido( + int? id_pedido) async { var con = await _dataBase.database; - return await con.delete(table, where: 'id_pedido = ?', whereArgs: [id_pedido]); + var result = await con.rawQuery(''' + SELECT * + FROM lista_pedido + inner join producto on lista_pedido.id_producto=producto.id_producto + where id_pedido=? + ''', [id_pedido]); // Aquí se pasa el parámetro + print(id_pedido); + print(result); + return result; } -} \ No newline at end of file + Future>?> mostrarPedidoDatosCliente( + int? id_pedido) async { + var con = await _dataBase.database; + var result = await con.rawQuery(''' +Select * from direccion d +inner join pedido p on d.id_direccion=p.id_direccion +inner join comunidad c on d.id_comunidad=c.id_comunidad +inner join municipio m on c.id_municipio=m.id_municipio +where p.id_pedido=? +group by p.id_pedido +limit 1 + ''', [id_pedido]); // Aquí se pasa el parámetro + print(id_pedido); + print(result); + return result; + +// SELECT +// pedido.id_pedido, +// pedido.fecha_entrega, +// pedido.id_status, +// direccion.calle, +// direccion.colonia, +// direccion.no_exterior, +// direccion.no_interior, +// direccion.num_telefono, +// FROM +// lista_pedido +// INNER JOIN +// producto ON lista_pedido.id_producto = producto.id_producto +// INNER JOIN +// pedido ON lista_pedido.id_pedido = pedido.id_pedido +// INNER JOIN +// direccion ON pedido.id_direccion = direccion.id_direccion +// INNER JOIN +// categoria ON producto.id_categoria = categoria.id_categoria +// WHERE +// lista_pedido.id_pedido = ? +// GROUP BY +// pedido.id_pedido; + } +} diff --git a/lib/database/database.dart b/lib/database/database.dart index b4244ce..3f67acb 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -35,7 +35,7 @@ class TiendaDataBase { CREATE TABLE producto( id_producto INTEGER PRIMARY KEY, producto VARCHAR(100), - precio NUMERIC, + precio REAL, descripcion VARCHAR(300), id_categoria INT, img_producto VARCHAR(150), @@ -96,15 +96,20 @@ class TiendaDataBase { CONSTRAINT pedido_direccion_fk FOREIGN KEY(id_direccion) REFERENCES direccion(id_direccion) );'''; db.execute(query8); + String query9 = ''' CREATE TABLE lista_pedido( id_lista_pedido INTEGER PRIMARY KEY, id_producto INT, + id_pedido int, cantidad INT, + precio Real, subtotal NUMERIC, + Constraint listaPpedido_pedido_fk Foreign key(id_pedido) references pedido(id_pedido), CONSTRAINT listaPedido_producto_fk FOREIGN KEY(id_producto) REFERENCES producto(id_producto) );'''; db.execute(query9); + String query10 = ''' INSERT INTO categoria (categoria) @@ -115,6 +120,52 @@ class TiendaDataBase { ; '''; db.execute(query10); + + String query11 = ''' + INSERT INTO producto + (producto, precio, descripcion, id_categoria) +VALUES + ('Pizza Grande de Peperoni', 200.50, 'Pizza Grande de 10 Rebanadas, con mucho peperoni y queso, orilla normal', 1), + ('Refresco 2L Pepsi Sabor cola', 29.00, 'Pepsi 2L sabor Cola', 2), + ('Agua de Jamaica 1L Marca La mamá de Pichis', 25.00, 'Agua de jamaica 100% natural', 3); + +'''; + db.execute(query11); + + String query12 = ''' + Insert into status(status)values('completado'),('En Proceso'),('cancelado') + '''; + db.execute(query12); + + String query13 = ''' + insert into municipio(municipio)values('Cortazar'),('Celaya'),('Salamanca'),('Villagran') + '''; + db.execute(query13); + String query14 = ''' + insert into comunidad(comunidad,id_municipio)values('Tierra Fria',1) + '''; + db.execute(query14); + String query15 = ''' + insert into direccion(id_comunidad,calle,colonia,no_exterior,no_interior,num_telefono,nombre_cliente) + values (1,'Alameda','Alameda',104,104,'4111549487','Miguel Vera Franco') + '''; + db.execute(query15); + + String query17 = ''' + insert into pedido(id_status,id_direccion,fecha_entrega)values(1,1,'2024-10-17') + '''; + db.execute(query17); + + String query16 = ''' + INSERT INTO lista_pedido(id_pedido, id_producto, cantidad, subtotal, precio) + VALUES + (1, 1, 2, 211, 105), + (1, 3, 3, 333, 111) + '''; + db.execute(query16); + // int? id_lista_pedido, id_producto, cantidad; + // double? subtotal; + print('se creo la base de datos'); }, ); } // initdatabase @@ -140,5 +191,4 @@ class TiendaDataBase { // var result = await con.query('categoria'); // return result.map((categoria)=>CategoriaModel.fromMap(categoria)).toList(); // } - } diff --git a/lib/main.dart b/lib/main.dart index 2baa9d4..beb9f39 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,6 @@ import 'package:flutter/material.dart'; import 'package:store_sqlite/routes/rutes.dart'; import 'package:store_sqlite/screens/MenuAppResponsiveScreen.dart'; -import 'package:store_sqlite/screens/login/login_ScreenH.dart'; -import 'package:store_sqlite/screens/login/login_screenV.dart'; -import 'package:store_sqlite/screens/loginResponsiveScreen.dart'; import 'package:store_sqlite/screens/menuApp/MenuApp_screenH.dart'; import 'package:store_sqlite/screens/menuApp/MenuApp_screenV.dart'; diff --git a/lib/models/producto_model.dart b/lib/models/producto_model.dart index ea86c1a..4c691fd 100644 --- a/lib/models/producto_model.dart +++ b/lib/models/producto_model.dart @@ -1,4 +1,3 @@ - class ProductoModel { int? id_producto; String? producto; @@ -18,7 +17,8 @@ class ProductoModel { return ProductoModel( id_producto: producto['id_producto'], producto: producto['producto'], - precio: producto['precio'], + precio: (producto['precio'] as num) + .toDouble(), // Conversión segura a double descripcion: producto['descripcion'], id_categoria: producto['id_categoria'], img_producto: producto['img_producto']); diff --git a/lib/routes/rutes.dart b/lib/routes/rutes.dart index bfecdb0..5566222 100644 --- a/lib/routes/rutes.dart +++ b/lib/routes/rutes.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:store_sqlite/screens/informacionPedido.dart'; import 'package:store_sqlite/screens/login/login_ScreenH.dart'; import 'package:store_sqlite/screens/login/login_screenV.dart'; import 'package:store_sqlite/screens/loginResponsiveScreen.dart'; @@ -6,11 +7,12 @@ import 'package:store_sqlite/screens/loginResponsiveScreen.dart'; class AppRoutes { static const menuScreen = '/MenuScreen'; static const loginScreen = '/loginScreen'; - + static const informacionPedido = '/informacionPedido'; static final routes = { //recibe una cadena , y un witget loginScreen: (context) => const loginResponsiveScreen( pantallaVerticalMobile: LoginScreenVertical(), - pantallaHorizontalMobile: LoginScreenHorizontal()) + pantallaHorizontalMobile: LoginScreenHorizontal()), + informacionPedido: (context) => Informacionpedido(), }; } diff --git a/lib/screens/informacionPedido.dart b/lib/screens/informacionPedido.dart new file mode 100644 index 0000000..c2025b6 --- /dev/null +++ b/lib/screens/informacionPedido.dart @@ -0,0 +1,40 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/pedido_controller.dart'; +import 'package:store_sqlite/screens/infromacionPedido/InformacionPedidoWidget.dart'; +import 'package:store_sqlite/screens/infromacionPedido/floatingButtonWidget.dart'; +import 'package:store_sqlite/screens/infromacionPedido/informacionClienteWidget.dart'; +import 'package:animated_floating_buttons/animated_floating_buttons.dart'; + +class Informacionpedido extends StatefulWidget { + const Informacionpedido({super.key}); + + @override + State createState() => _InformacionpedidoState(); +} + +class _InformacionpedidoState extends State { + PedidoController informacionPedido = PedidoController(); + + late int? id = 0; + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + final arguments = (ModalRoute.of(context)?.settings.arguments ?? + {}) as Map; + // print(arguments['id_pedido']); + id = arguments['id_pedido']; + return Scaffold( + appBar: AppBar(title: Text('Datos pedido $id')), + body: Column( + children: [ + InformacionClientewidget(id), + Informacionpedidowidget(id), + ], + ), + floatingActionButton: Floatingbuttonwidget(id)); + } +} diff --git a/lib/screens/infromacionPedido/InformacionPedidoWidget.dart b/lib/screens/infromacionPedido/InformacionPedidoWidget.dart new file mode 100644 index 0000000..2fa6d75 --- /dev/null +++ b/lib/screens/infromacionPedido/InformacionPedidoWidget.dart @@ -0,0 +1,64 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/pedido_controller.dart'; + +class Informacionpedidowidget extends StatefulWidget { + final int? id; + const Informacionpedidowidget(this.id, {super.key}); // Constructor modificado + + @override + State createState() => + _InformacionpedidowidgetState(); +} + +class _InformacionpedidowidgetState extends State { + PedidoController informacionPedido = PedidoController(); + @override + Widget build(BuildContext context) { + final arguments = (ModalRoute.of(context)?.settings.arguments ?? + {}) as Map; + // print(arguments['id_pedido']); + + return Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * .58, + decoration: BoxDecoration(), + child: FutureBuilder>?>( + future: informacionPedido + .mostrarPedidosConListaPedido(widget.id), // Usar el id aquí + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center(child: Text('No se encontraron pedidos')); + } else { + List> pedidos = snapshot.data!; + return ListView.builder( + itemCount: pedidos.length, + itemBuilder: (context, index) { + var pedido = pedidos[index]; + return Container( + child: ListTile( + title: Text('Artículo: ${pedido['producto']}'), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Cantidad: ${pedido['cantidad']}'), + SizedBox(height: 4.0), // Espacio entre textos + Text('Precio: \$${pedido['precio']}', + style: TextStyle(fontWeight: FontWeight.bold)), + SizedBox(height: 4.0), // Espacio entre textos + Text('Subtotal: ${pedido['']}'), + ], + ), + ), + ); + }, + ); + } + }, + ), + ); + } +} diff --git a/lib/screens/infromacionPedido/floatingButtonWidget.dart b/lib/screens/infromacionPedido/floatingButtonWidget.dart new file mode 100644 index 0000000..b3cf2b9 --- /dev/null +++ b/lib/screens/infromacionPedido/floatingButtonWidget.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:animated_floating_buttons/animated_floating_buttons.dart'; + +class Floatingbuttonwidget extends StatefulWidget { + final int? id; + const Floatingbuttonwidget(this.id, {super.key}); + + @override + State createState() => _FloatingbuttonwidgetState(); +} + +class _FloatingbuttonwidgetState extends State { + final GlobalKey key = + GlobalKey(); + Widget float1() { + return Container( + child: FloatingActionButton( + onPressed: null, + heroTag: "new", + tooltip: 'First button', + child: Icon(Icons.add), + ), + ); + } + + Widget float2() { + return Container( + child: FloatingActionButton( + onPressed: () { + print(widget.id); + }, + heroTag: "edit", + tooltip: 'Second button', + child: Icon(Icons.edit), + ), + ); + } + + @override + Widget build(BuildContext context) { + return AnimatedFloatingActionButton( + //Fab list + fabButtons: [float1(), float2()], + key: key, + colorStartAnimation: Colors.blue, + colorEndAnimation: Colors.red, + animatedIconData: AnimatedIcons.menu_close //To principal button + ); + } +} diff --git a/lib/screens/infromacionPedido/informacionClienteWidget.dart b/lib/screens/infromacionPedido/informacionClienteWidget.dart new file mode 100644 index 0000000..93f906e --- /dev/null +++ b/lib/screens/infromacionPedido/informacionClienteWidget.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/pedido_controller.dart'; + +class InformacionClientewidget extends StatefulWidget { + final int? id; + const InformacionClientewidget(this.id, + {super.key}); // Constructor modificado + + @override + State createState() => + _InformacionpedidowidgetState(); +} + +class _InformacionpedidowidgetState extends State { + PedidoController informacionPedido = PedidoController(); + @override + Widget build(BuildContext context) { + final arguments = (ModalRoute.of(context)?.settings.arguments ?? + {}) as Map; + // print(arguments['id_pedido']); + + return Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height * .29, + decoration: BoxDecoration(color: const Color.fromARGB(255, 57, 56, 51)), + child: FutureBuilder>?>( + future: informacionPedido + .mostrarPedidoDatosCliente(widget.id), // Usar el id aquí + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return Center(child: Text('Error: ${snapshot.error}')); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return Center(child: Text('No se encontraron pedidos')); + } else { + List> pedidos = snapshot.data!; + return ListView.builder( + itemCount: pedidos.length, + itemBuilder: (context, index) { + var pedido = pedidos[index]; + return Container( + child: ListTile( + title: Text('Datos De Entrega:', + style: TextStyle(fontWeight: FontWeight.bold)), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Cliente: ${pedido['nombre_cliente']}'), + IconButton( + onPressed: () { + print(' ${pedido['num_telefono']}'); + }, + icon: Text( + 'Num Tel: ${pedido['num_telefono']}', + style: TextStyle(fontWeight: FontWeight.bold), + )), + + Text( + 'Municipio:${pedido['municipio']}', + ), + SizedBox(height: 4.0), // Espacio entre textos + Text('Comunidad: ${pedido['comunidad']}'), + SizedBox(height: 4.0), + Text('Colonia: ${pedido['colonia']}'), + SizedBox(height: 4.0), + Text('Calle: ${pedido['calle']}'), + SizedBox(height: 4.0), + Text('No.Ext: ${pedido['no_exterior']}'), + SizedBox(height: 4.0), + ], + ), + ), + ); + }, + ); + } + }, + ), + ); + } +} diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index 8543b34..f72edd4 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -1,8 +1,10 @@ +import 'package:animated_botton_navigation/animated_botton_navigation.dart'; import 'package:flutter/material.dart'; -import 'package:sqflite/sqflite.dart'; -import 'package:store_sqlite/controller/categoria_controller.dart'; +import 'package:store_sqlite/controller/producto_controller.dart'; import 'package:store_sqlite/database/database.dart'; -import 'package:store_sqlite/models/categoria_model.dart'; +import 'package:store_sqlite/models/producto_model.dart'; +import 'package:flutter_product_card/flutter_product_card.dart'; +import 'package:store_sqlite/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart'; class MenuappScreenv extends StatefulWidget { const MenuappScreenv({super.key}); @@ -13,49 +15,51 @@ class MenuappScreenv extends StatefulWidget { class _MenuappScreenvState extends State { late TiendaDataBase categoriaDB; - late CategoriaController categoriaController; + late ProductoController productoController; + int _currentIndex = 0; + + final List _pages = [ + Center(child: Pedidoslistawidget()), + Center(child: Text('Search Page')), + Center(child: Text('Profile Page')), + ]; + @override void initState() { super.initState(); - categoriaController = CategoriaController(); + productoController = ProductoController(); } @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text('Menu App'), - actions: [ - IconButton( - onPressed: () {}, - icon: Icon(Icons.add), - ), - ], - backgroundColor: const Color.fromARGB(131, 50, 45, 45), - ), - body: FutureBuilder( - future: categoriaController.mostrarTodasLasCategorias(), - builder: (context, AsyncSnapshot?> snapshot) { - if (snapshot.hasData) { - return ListView.builder( - itemCount: snapshot.data!.length, - itemBuilder: (context, index) { - return Text( - 'los valores del snapshot= ${snapshot.data![index].categoria}'); - //MovieViewItem(moviesDAO: snapshot.data![index],); - }, - ); - } else { - if (snapshot.hasError) { - return Center( - child: Text(snapshot.error.toString()), - ); - } else { - return Center( - child: CircularProgressIndicator(), - ); - } - } - })); + appBar: AppBar( + title: Text('Glorys Pizza Admin App'), + actions: [ + IconButton( + onPressed: () {}, + icon: Icon(Icons.add), + ), + ], + backgroundColor: const Color.fromARGB(131, 33, 31, 31), + ), + body: _pages[_currentIndex], + bottomNavigationBar: AnimatedBottomNavigation( + height: 70, + indicatorSpaceBotton: 25, + selectedColor: Colors.black, + icons: [ + Icons.motorcycle, + Icons.calendar_month, + Icons.person, + ], + currentIndex: _currentIndex, + onTapChange: (index) { + setState(() { + _currentIndex = index; + }); + }, + ), + ); } } diff --git a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart new file mode 100644 index 0000000..8bbd963 --- /dev/null +++ b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart @@ -0,0 +1,134 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/pedido_controller.dart'; +import 'package:store_sqlite/models/pedido_model.dart'; + +class Pedidoslistawidget extends StatefulWidget { + const Pedidoslistawidget({super.key}); + + @override + State createState() => _PedidoslistawidgetState(); +} + +class _PedidoslistawidgetState extends State { + late PedidoController pedidoController; + + @override + void initState() { + pedidoController = PedidoController(); + print('////////////////////////////////////////////'); + pedidoController.mostrarPedidosConListaPedido(1); + print('////////////////////////////////////////////'); + super.initState(); + } + + Color getColorByStatus(int? idStatus) { + switch (idStatus) { + case 1: + return Colors.green; // Si el idStatus es 1, el color será verde. + case 2: + return Colors.red; // Si el idStatus es 2, el color será rojo. + case 3: + return Colors.white; // Si el idStatus es 3, el color será blanco. + default: + return Colors + .grey; // Color por defecto si no es ninguno de los anteriores. + } + } + + Icon getIconStatus(int? idStatus) { + switch (idStatus) { + case 1: + return Icon( + Icons.done, + color: Colors.green, + ); + case 2: + return Icon( + Icons.cancel, + color: Colors.red, + ); + case 3: + return Icon( + Icons.hourglass_empty, + color: Colors.grey, + ); + } + return Icon(Icons.error); + } + + @override + Widget build(BuildContext context) { + var LargoContenedorList = MediaQuery.of(context).size.width * .1; + return Scaffold( + body: FutureBuilder( + future: pedidoController.mostrarTodosLosPedidos(), + builder: (context, AsyncSnapshot?> snapshot) { + if (snapshot.hasData) { + return ListView.builder( + itemCount: snapshot.data!.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: () { + Navigator.pushNamed(context, '/informacionPedido', + arguments: { + 'id_pedido': snapshot.data![index].id_pedido + }); + }, + child: Container( + width: LargoContenedorList, + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: const Color.fromARGB(40, 75, 39, 39), + border: Border( + left: BorderSide( + color: getColorByStatus( + snapshot.data![index].id_status), + width: 4, + ), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Texto del pedido y fecha de entrega + Expanded( + child: Text( + 'No_pedido: ${snapshot.data![index].id_pedido}\nFecha entrega: ${snapshot.data![index].fecha_entrega}', + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 16, + // color: Colors.black, + ), + ), + ), + // Ícono que representa el estado del pedido + getIconStatus(snapshot.data![index].id_status), + ], + ), + ), + ), + ); + }, + + //${snapshot.data![index].fecha_entrega}', + //); + ); + } else { + if (snapshot.hasError) { + return Center( + child: Text(snapshot.error.toString()), + ); + } else { + return Center( + child: CircularProgressIndicator(), + ); + } + } + }, + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index 3025d92..1fa9a7f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,22 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + animated_botton_navigation: + dependency: "direct main" + description: + name: animated_botton_navigation + sha256: "4c8eb1c5d296c3f1e2144d9965a96ac71b02ee24b8577a3927aede6a86d9ba65" + url: "https://pub.dev" + source: hosted + version: "0.0.7" + animated_floating_buttons: + dependency: "direct main" + description: + name: animated_floating_buttons + sha256: cd89653ab917fb0d7ab04d5b5d6807c75de3f002de99b10f63fcf3c5c7133d60 + url: "https://pub.dev" + source: hosted + version: "0.0.2" async: dependency: transitive description: @@ -78,6 +94,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + flutter_product_card: + dependency: "direct main" + description: + name: flutter_product_card + sha256: "7dbad88b0138de2e3d4a671c81c049a34d1f9d56bd582190ab81c6ec9f23fe17" + url: "https://pub.dev" + source: hosted + version: "0.0.7" flutter_test: dependency: "direct dev" description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index 5ebcc6d..2fa72b6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -32,6 +32,9 @@ dependencies: sdk: flutter sqflite: ^2.3.3+1 path_provider: ^2.1.4 + flutter_product_card: ^0.0.7 + animated_botton_navigation: ^0.0.7 + animated_floating_buttons: ^0.0.2 # The following adds the Cupertino Icons font to your application. From dd99b173d6e1d06f9fef692c39db3ab702f33772 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Fri, 18 Oct 2024 10:17:46 -0600 Subject: [PATCH 5/9] pantallas creadas= producto, drawer, menu,button --- assets/img/logo_pizza.jfif | Bin 0 -> 51756 bytes lib/controller/producto_controller.dart | 12 +++ lib/routes/rutes.dart | 6 ++ lib/screens/NuevoPedido.dart | 59 ++++++++++++ lib/screens/NuevoPedido/cardWidget.dart | 58 ++++++++++++ lib/screens/carrito_screens.dart | 17 ++++ lib/screens/informacionPedido.dart | 9 +- .../dropDownButtonListWidget.dart | 86 ++++++++++++++++++ .../floatingButtonWidget.dart | 4 +- .../informacionClienteWidget.dart | 2 +- lib/screens/menuApp/MenuApp_screenV.dart | 75 +++++++++++++-- .../widgetMenuApp/PedidosListaWidget.dart | 15 +-- lib/screens/menuApp/widgetMenuApp/drawer.dart | 67 ++++++++++++++ pubspec.lock | 24 +++++ pubspec.yaml | 7 +- 15 files changed, 420 insertions(+), 21 deletions(-) create mode 100644 assets/img/logo_pizza.jfif create mode 100644 lib/screens/NuevoPedido.dart create mode 100644 lib/screens/NuevoPedido/cardWidget.dart create mode 100644 lib/screens/carrito_screens.dart create mode 100644 lib/screens/infromacionPedido/dropDownButtonListWidget.dart create mode 100644 lib/screens/menuApp/widgetMenuApp/drawer.dart diff --git a/assets/img/logo_pizza.jfif b/assets/img/logo_pizza.jfif new file mode 100644 index 0000000000000000000000000000000000000000..179544877e8f301f0ae770f224d32d1137701b54 GIT binary patch literal 51756 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 ProductoModel.fromMap(producto)).toList(); } + Future>?> mostrarProductosConCategoria() async { + var con = await _dataBase.database; + var result = await con.rawQuery( + ''' + SELECT * + FROM producto p + inner join categoria c on p.id_categoria=c.id_categoria + ''', + ); + return result; + } + Future actualizarProducto(String table, Map row) async { var con = await _dataBase.database; return await con.update(table, row, diff --git a/lib/routes/rutes.dart b/lib/routes/rutes.dart index 5566222..6914bbf 100644 --- a/lib/routes/rutes.dart +++ b/lib/routes/rutes.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:store_sqlite/screens/NuevoPedido.dart'; +import 'package:store_sqlite/screens/carrito_screens.dart'; import 'package:store_sqlite/screens/informacionPedido.dart'; import 'package:store_sqlite/screens/login/login_ScreenH.dart'; import 'package:store_sqlite/screens/login/login_screenV.dart'; @@ -8,11 +10,15 @@ class AppRoutes { static const menuScreen = '/MenuScreen'; static const loginScreen = '/loginScreen'; static const informacionPedido = '/informacionPedido'; + static const nuevoPedido = '/crearPedido'; + static const carrito = '/carrito'; static final routes = { //recibe una cadena , y un witget loginScreen: (context) => const loginResponsiveScreen( pantallaVerticalMobile: LoginScreenVertical(), pantallaHorizontalMobile: LoginScreenHorizontal()), informacionPedido: (context) => Informacionpedido(), + nuevoPedido: (context) => Nuevopedido(), + carrito: (contexto) => CarritoScreens(), }; } diff --git a/lib/screens/NuevoPedido.dart b/lib/screens/NuevoPedido.dart new file mode 100644 index 0000000..322399e --- /dev/null +++ b/lib/screens/NuevoPedido.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/producto_controller.dart'; +import 'package:store_sqlite/models/producto_model.dart'; +import 'package:store_sqlite/screens/NuevoPedido/cardWidget.dart'; + +class Nuevopedido extends StatefulWidget { + const Nuevopedido({super.key}); + + @override + State createState() => _NuevopedidoState(); +} + +class _NuevopedidoState extends State { + late ProductoController productoController = ProductoController(); + void initState() { + super.initState(); + } + + @override + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + actions: [ + IconButton( + onPressed: () { + Navigator.pushNamed(context, '/carrito'); + }, + icon: Icon(Icons.shop)) + ], + ), + body: FutureBuilder>?>( + future: productoController.mostrarProductosConCategoria(), + builder: + (context, AsyncSnapshot>?> snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center(child: CircularProgressIndicator()); + } else if (snapshot.hasError) { + return const Center(child: Text('Something went wrong :(')); + } else if (!snapshot.hasData || snapshot.data!.isEmpty) { + return const Center(child: Text('No products found.')); + } + + return GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: .4, + crossAxisSpacing: .1, + mainAxisSpacing: 0), + itemCount: snapshot.data!.length, + itemBuilder: (BuildContext context, int index) { + return Cardwidget(snapshot.data![index]); + }, + ); + }, + ), + ); + } +} diff --git a/lib/screens/NuevoPedido/cardWidget.dart b/lib/screens/NuevoPedido/cardWidget.dart new file mode 100644 index 0000000..2831f57 --- /dev/null +++ b/lib/screens/NuevoPedido/cardWidget.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_product_card/flutter_product_card.dart'; +import 'package:counter_button/counter_button.dart'; + +class Cardwidget extends StatefulWidget { + final Map producto; + Cardwidget(this.producto, {super.key}); + + @override + State createState() => _CardwidgetState(); +} + +class _CardwidgetState extends State { + int _counterValue = 0; + + @override + Widget build(BuildContext context) { + double precio = widget.producto['precio']; + return Column( + children: [ + ProductCard( + imageUrl: + 'https://encrypted-tbn3.gstatic.com/shopping?q=tbn:ANd9GcQndSK7hvssofrM2uzv75NxVjrkAwH3RwyqWcBesUsmq1ipmkuljRr6x_SRbCKaBXvjTR9CKfAaEFtmUFw-69o52wgVMgk2hp8KDYr4FvKtQ8ZfKewgOW4gDQ&usqp=CAE4', + categoryName: '${widget.producto['categoria']}', + productName: '${widget.producto['producto']}', + price: precio, + currency: '\$', + onTap: () { + // Handle card tap event + }, + cardColor: Colors.white, + textColor: Colors.black, + borderRadius: 6.0, + ), + // Usa SizedBox para controlar el espacio entre el ProductCard y el CounterButton + SizedBox(height: 1), // Ajusta este valor para el espaciado deseado + CounterButton( + loading: false, + onChange: (int val) { + setState(() { + _counterValue = val; + }); + }, + count: _counterValue, + countColor: Colors.purple, + buttonColor: Colors.purpleAccent, + progressColor: Colors.purpleAccent, + ), + // Otro SizedBox para el espacio entre CounterButton e IconButton + SizedBox(height: 1), // Ajusta este valor también + IconButton( + onPressed: () {}, + icon: Icon(Icons.add_shopping_cart_rounded), + ), + ], + ); + } +} diff --git a/lib/screens/carrito_screens.dart b/lib/screens/carrito_screens.dart new file mode 100644 index 0000000..074da1a --- /dev/null +++ b/lib/screens/carrito_screens.dart @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; + +class CarritoScreens extends StatefulWidget { + const CarritoScreens({super.key}); + + @override + State createState() => _CarritoScreensState(); +} + +class _CarritoScreensState extends State { + @override + Widget build(BuildContext context) { + return Scaffold(appBar: AppBar( + title: Text('Carrito De Compras'), + ),); + } +} diff --git a/lib/screens/informacionPedido.dart b/lib/screens/informacionPedido.dart index c2025b6..8390531 100644 --- a/lib/screens/informacionPedido.dart +++ b/lib/screens/informacionPedido.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:store_sqlite/controller/pedido_controller.dart'; import 'package:store_sqlite/screens/infromacionPedido/InformacionPedidoWidget.dart'; +import 'package:store_sqlite/screens/infromacionPedido/dropDownButtonListWidget.dart'; import 'package:store_sqlite/screens/infromacionPedido/floatingButtonWidget.dart'; import 'package:store_sqlite/screens/infromacionPedido/informacionClienteWidget.dart'; import 'package:animated_floating_buttons/animated_floating_buttons.dart'; @@ -16,6 +17,7 @@ class _InformacionpedidoState extends State { PedidoController informacionPedido = PedidoController(); late int? id = 0; + late int? id_status = 0; @override void initState() { super.initState(); @@ -27,8 +29,13 @@ class _InformacionpedidoState extends State { {}) as Map; // print(arguments['id_pedido']); id = arguments['id_pedido']; + id_status = arguments['id_status']; + return Scaffold( - appBar: AppBar(title: Text('Datos pedido $id')), + appBar: AppBar( + title: Text('Datos pedido $id'), + // actions: [Dropdownbuttonlistwidget(id_status)], + ), body: Column( children: [ InformacionClientewidget(id), diff --git a/lib/screens/infromacionPedido/dropDownButtonListWidget.dart b/lib/screens/infromacionPedido/dropDownButtonListWidget.dart new file mode 100644 index 0000000..f7dcf87 --- /dev/null +++ b/lib/screens/infromacionPedido/dropDownButtonListWidget.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:store_sqlite/controller/status_controller.dart'; +import 'package:store_sqlite/models/lista_pedido_model.dart'; +import 'package:store_sqlite/models/status_model.dart'; + +class Dropdownbuttonlistwidget extends StatefulWidget { + const Dropdownbuttonlistwidget(this.id_status, {super.key}); + final int? id_status; +// Constructor modificado + + @override + State createState() => + _DropdownbuttonlistwidgetState(); +} + +class _DropdownbuttonlistwidgetState extends State { + late StatusController statusController = StatusController(); + final List items = [ + 'Item1', + 'Item2', + 'Item3', + 'Item4', + ]; + + ValueNotifier selectedValueNotifier = ValueNotifier(null); + + @override + void initState() { + super.initState(); + print('+++++++++++++++++++++++++++++++++++++++++'); + Lista(); + } + + void Lista() async { + List? list = await statusController.mostrarTodosLosStatus(); + print(list); // Esto imprimirá la lista cuando esté disponible. + } + + @override + Widget build(BuildContext context) { + return Container( + width: 200, // Ajusta el ancho del Container + child: ValueListenableBuilder( + valueListenable: selectedValueNotifier, + builder: (context, selectedValue, child) { + return DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text( + '${widget.id_status}', + style: TextStyle( + fontSize: 14, + color: Theme.of(context).hintColor, + ), + ), + items: items + .map((String item) => DropdownMenuItem( + value: item, + child: Text( + item, + style: const TextStyle( + fontSize: 14, + ), + ), + )) + .toList(), + value: selectedValue, + onChanged: (String? value) { + selectedValueNotifier.value = value; + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.symmetric(horizontal: 16), + height: 40, + width: 160, // Ajusta el ancho del DropdownButton2 + ), + menuItemStyleData: const MenuItemStyleData( + height: 40, + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/screens/infromacionPedido/floatingButtonWidget.dart b/lib/screens/infromacionPedido/floatingButtonWidget.dart index b3cf2b9..b7b1f91 100644 --- a/lib/screens/infromacionPedido/floatingButtonWidget.dart +++ b/lib/screens/infromacionPedido/floatingButtonWidget.dart @@ -15,7 +15,9 @@ class _FloatingbuttonwidgetState extends State { Widget float1() { return Container( child: FloatingActionButton( - onPressed: null, + onPressed: () { + Navigator.pushNamed(context, '/crearPedido'); + }, heroTag: "new", tooltip: 'First button', child: Icon(Icons.add), diff --git a/lib/screens/infromacionPedido/informacionClienteWidget.dart b/lib/screens/infromacionPedido/informacionClienteWidget.dart index 93f906e..5463fe5 100644 --- a/lib/screens/infromacionPedido/informacionClienteWidget.dart +++ b/lib/screens/infromacionPedido/informacionClienteWidget.dart @@ -4,7 +4,7 @@ import 'package:store_sqlite/controller/pedido_controller.dart'; class InformacionClientewidget extends StatefulWidget { final int? id; const InformacionClientewidget(this.id, - {super.key}); // Constructor modificado + {super.key}); @override State createState() => diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index f72edd4..799ed68 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -5,6 +5,7 @@ import 'package:store_sqlite/database/database.dart'; import 'package:store_sqlite/models/producto_model.dart'; import 'package:flutter_product_card/flutter_product_card.dart'; import 'package:store_sqlite/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart'; +import 'package:store_sqlite/screens/menuApp/widgetMenuApp/drawer.dart'; class MenuappScreenv extends StatefulWidget { const MenuappScreenv({super.key}); @@ -14,8 +15,6 @@ class MenuappScreenv extends StatefulWidget { } class _MenuappScreenvState extends State { - late TiendaDataBase categoriaDB; - late ProductoController productoController; int _currentIndex = 0; final List _pages = [ @@ -24,20 +23,78 @@ class _MenuappScreenvState extends State { Center(child: Text('Profile Page')), ]; - @override - void initState() { - super.initState(); - productoController = ProductoController(); - } - @override Widget build(BuildContext context) { return Scaffold( + drawer: SafeArea( + child: Container( + child: ListTileTheme( + textColor: Colors.white, + iconColor: Colors.white, + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Container( + width: 128.0, + height: 128.0, + margin: const EdgeInsets.only( + top: 24.0, + bottom: 64.0, + ), + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + color: Colors.black26, + shape: BoxShape.circle, + ), + child: Image.asset( + 'assets/img/logo_pizza.jfif', + ), + ), + ListTile( + onTap: () {}, + leading: Icon(Icons.food_bank), + title: Text('Productos'), + ), + ListTile( + onTap: () {}, + leading: Icon(Icons.category), + title: Text('Categorias'), + ), + ListTile( + onTap: () {}, + leading: Icon(Icons.location_city), + title: Text('Municipios'), + ), + ListTile( + onTap: () {}, + leading: Icon(Icons.gps_fixed), + title: Text('Comunidades'), + ), + Spacer(), + DefaultTextStyle( + style: TextStyle( + fontSize: 12, + color: Colors.white54, + ), + child: Container( + margin: const EdgeInsets.symmetric( + vertical: 16.0, + ), + child: Text('Terms of Service | Privacy Policy'), + ), + ), + ], + ), + ), + ), + ), appBar: AppBar( title: Text('Glorys Pizza Admin App'), actions: [ IconButton( - onPressed: () {}, + onPressed: () { + Navigator.pushNamed(context, '/crearPedido'); + }, icon: Icon(Icons.add), ), ], diff --git a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart index 8bbd963..6762582 100644 --- a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart +++ b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart @@ -38,22 +38,22 @@ class _PedidoslistawidgetState extends State { Icon getIconStatus(int? idStatus) { switch (idStatus) { case 1: - return Icon( + return const Icon( Icons.done, color: Colors.green, ); case 2: - return Icon( + return const Icon( Icons.cancel, color: Colors.red, ); case 3: - return Icon( + return const Icon( Icons.hourglass_empty, color: Colors.grey, ); } - return Icon(Icons.error); + return const Icon(Icons.error); } @override @@ -73,7 +73,8 @@ class _PedidoslistawidgetState extends State { onTap: () { Navigator.pushNamed(context, '/informacionPedido', arguments: { - 'id_pedido': snapshot.data![index].id_pedido + 'id_pedido': snapshot.data![index].id_pedido, + 'id_status': snapshot.data![index].id_status }); }, child: Container( @@ -98,7 +99,7 @@ class _PedidoslistawidgetState extends State { child: Text( 'No_pedido: ${snapshot.data![index].id_pedido}\nFecha entrega: ${snapshot.data![index].fecha_entrega}', textAlign: TextAlign.left, - style: TextStyle( + style: const TextStyle( fontSize: 16, // color: Colors.black, ), @@ -122,7 +123,7 @@ class _PedidoslistawidgetState extends State { child: Text(snapshot.error.toString()), ); } else { - return Center( + return const Center( child: CircularProgressIndicator(), ); } diff --git a/lib/screens/menuApp/widgetMenuApp/drawer.dart b/lib/screens/menuApp/widgetMenuApp/drawer.dart new file mode 100644 index 0000000..020708a --- /dev/null +++ b/lib/screens/menuApp/widgetMenuApp/drawer.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_advanced_drawer/flutter_advanced_drawer.dart'; + +class DrawerMain extends StatelessWidget { + DrawerMain({super.key}); + + final _advancedDrawerController = AdvancedDrawerController(); + + @override + Widget build(BuildContext context) { + return AdvancedDrawer( + backdrop: Container( + width: double.infinity, + height: double.infinity, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Colors.blueGrey, Colors.blueGrey.withOpacity(0.2)], + ), + ), + ), + controller: _advancedDrawerController, + animationCurve: Curves.easeInOut, + animationDuration: const Duration(milliseconds: 300), + animateChildDecoration: true, + rtlOpening: false, + // openScale: 1.0, + disabledGestures: false, + childDecoration: const BoxDecoration( + // NOTICE: Uncomment if you want to add shadow behind the page. + // Keep in mind that it may cause animation jerks. + // boxShadow: [ + // BoxShadow( + // color: Colors.black12, + // blurRadius: 0.0, + // ), + // ], + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + drawer: Container(), + child: Scaffold( + appBar: AppBar( + title: const Text('Advanced Drawer Example'), + leading: IconButton( + onPressed: _handleMenuButtonPressed, + icon: ValueListenableBuilder( + valueListenable: _advancedDrawerController, + builder: (_, value, __) { + return AnimatedSwitcher( + duration: Duration(milliseconds: 250), + child: Icon( + value.visible ? Icons.clear : Icons.menu, + key: ValueKey(value.visible), + ), + ); + }, + ), + ), + ), + body: Container(), + ), + ); + } + + void _handleMenuButtonPressed() {} +} diff --git a/pubspec.lock b/pubspec.lock index 1fa9a7f..3b3d035 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + counter_button: + dependency: "direct main" + description: + name: counter_button + sha256: "36992a764f513c9780195ec4613676d5d3dbe1685ccdb702bd1de7eb2cfe72d9" + url: "https://pub.dev" + source: hosted + version: "1.0.1" cupertino_icons: dependency: "direct main" description: @@ -65,6 +73,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + sha256: b0fe8d49a030315e9eef6c7ac84ca964250155a6224d491c1365061bc974a9e1 + url: "https://pub.dev" + source: hosted + version: "2.3.9" fake_async: dependency: transitive description: @@ -86,6 +102,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_advanced_drawer: + dependency: "direct main" + description: + name: flutter_advanced_drawer + sha256: "4d475bf48b30fcafe5ba9822ca302ea0aa9240317882fffd8450ba96a7e33105" + url: "https://pub.dev" + source: hosted + version: "1.3.6" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index 2fa72b6..bf27eb1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,9 @@ dependencies: flutter_product_card: ^0.0.7 animated_botton_navigation: ^0.0.7 animated_floating_buttons: ^0.0.2 + dropdown_button2: ^2.3.9 + counter_button: ^1.0.1 + flutter_advanced_drawer: ^1.3.6 # The following adds the Cupertino Icons font to your application. @@ -64,8 +67,8 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg + assets: + - assets/img/ # - images/a_dot_ham.jpeg # An image asset can refer to one or more resolution-specific "variants", see From f665f0667776c84c704950df0172b81544db69b9 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Sat, 19 Oct 2024 00:23:52 -0600 Subject: [PATCH 6/9] =?UTF-8?q?se=20agreg=C3=B3=20el=20calendario,=20la=20?= =?UTF-8?q?modal=20del=20calendario,=20los=20puntos=20en=20el=20calendario?= =?UTF-8?q?,=20lista=20en=20calendario,=20solo=20hace=20falta=20mandar=20l?= =?UTF-8?q?os=20datos=20que=20deben=20de=20ir=20y=20reemplazar=20los=20vie?= =?UTF-8?q?jos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 2 +- lib/controller/pedido_controller.dart | 12 ++ lib/controller/producto_controller.dart | 1 + lib/database/database.dart | 6 +- lib/main.dart | 2 +- lib/screens/calendarScreen.dart | 147 ++++++++++++++++++ .../calendar_widget/modalCalendarWidget.dart | 39 +++++ lib/screens/menuApp/MenuApp_screenV.dart | 13 +- .../widgetMenuApp/PedidosListaWidget.dart | 14 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 + pubspec.lock | 117 ++++++++++++++ pubspec.yaml | 83 +++++----- .../flutter/generated_plugin_registrant.cc | 6 + windows/flutter/generated_plugins.cmake | 2 + 14 files changed, 388 insertions(+), 60 deletions(-) create mode 100644 lib/screens/calendarScreen.dart create mode 100644 lib/screens/calendar_widget/modalCalendarWidget.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index b2e72ac..c0b77eb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -24,7 +24,7 @@ android { applicationId = "com.example.store_sqlite" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion + minSdk = 26 targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName diff --git a/lib/controller/pedido_controller.dart b/lib/controller/pedido_controller.dart index 3571002..f131a09 100644 --- a/lib/controller/pedido_controller.dart +++ b/lib/controller/pedido_controller.dart @@ -41,6 +41,18 @@ class PedidoController { return result; } + Future>?> mostrarTodosLosPedidosSinId() async { + var con = await _dataBase.database; + var result = await con.rawQuery(''' + SELECT * + FROM pedido p + inner join direccion d on p.id_direccion=d.id_direccion + '''); // Aquí se pasa el parámetro + + print(result); + return result; + } + Future>?> mostrarPedidoDatosCliente( int? id_pedido) async { var con = await _dataBase.database; diff --git a/lib/controller/producto_controller.dart b/lib/controller/producto_controller.dart index 3ab9125..b350539 100644 --- a/lib/controller/producto_controller.dart +++ b/lib/controller/producto_controller.dart @@ -27,6 +27,7 @@ class ProductoController { return result; } + Future actualizarProducto(String table, Map row) async { var con = await _dataBase.database; return await con.update(table, row, diff --git a/lib/database/database.dart b/lib/database/database.dart index 3f67acb..ab4f431 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -152,7 +152,7 @@ VALUES db.execute(query15); String query17 = ''' - insert into pedido(id_status,id_direccion,fecha_entrega)values(1,1,'2024-10-17') + insert into pedido(id_status,id_direccion,fecha_entrega)values(1,1,'2024-10-18'),(2,1,'2024-11-19'),(3,1,'2024-11-20') '''; db.execute(query17); @@ -160,7 +160,9 @@ VALUES INSERT INTO lista_pedido(id_pedido, id_producto, cantidad, subtotal, precio) VALUES (1, 1, 2, 211, 105), - (1, 3, 3, 333, 111) + (1, 3, 3, 333, 111), + (2, 3, 3, 333, 111), + (3, 3, 3, 333, 111) '''; db.execute(query16); // int? id_lista_pedido, id_producto, cantidad; diff --git a/lib/main.dart b/lib/main.dart index beb9f39..1ee4db2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,7 +14,7 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Material App', debugShowCheckedModeBanner: false, - theme: ThemeData.dark(), + theme: ThemeData.light(), home: const Menuappresponsivescreen( pantallaVerticalMobile: MenuappScreenv(), pantallaHorizontalMobile: MenuappScreenH()), diff --git a/lib/screens/calendarScreen.dart b/lib/screens/calendarScreen.dart new file mode 100644 index 0000000..0497dfb --- /dev/null +++ b/lib/screens/calendarScreen.dart @@ -0,0 +1,147 @@ +import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/pedido_controller.dart'; +import 'package:table_calendar/table_calendar.dart'; +import 'package:intl/intl.dart'; + +class TableBasicsExample extends StatefulWidget { + @override + _TableBasicsExampleState createState() => _TableBasicsExampleState(); +} + +class _TableBasicsExampleState extends State { + CalendarFormat _calendarFormat = CalendarFormat.month; + DateTime _focusedDay = DateTime.now(); + DateTime? _selectedDay; + DateTime? _selectedDate; + Map mySelectedEvents = {}; + PedidoController pedidoController = PedidoController(); + + @override + void initState() { + super.initState(); + main(); // Cargar eventos al inicio + } + + Future>?> recuperandoDatos() async { + List>? datos = + await pedidoController.mostrarTodosLosPedidosSinId(); + print('Imprimiendo los datos de la base de datos:'); + return datos; + } + + Future extraerDatos() async { + var datos = await recuperandoDatos(); + + if (datos != null && datos.isNotEmpty) { + for (var dato in datos) { + String fecha = dato['fecha_entrega']; + String eventTitle = dato['colonia']; + String eventDescp = dato['calle']; + + // Revisa si la fecha se almacena en el formato correcto + print('Fecha: $fecha, Título: $eventTitle, Descripción: $eventDescp'); + + mySelectedEvents[fecha] ??= []; + mySelectedEvents[fecha]!.add({ + 'eventTitle': eventTitle, + 'eventDescp': eventDescp, + }); + } + + print('Eventos cargados: $mySelectedEvents'); + } else { + print('No se obtuvieron datos o la lista está vacía.'); + } + } + + Future main() async { + await extraerDatos(); + setState(() {}); + } + + List _listOfDayEvents(DateTime dateTime) { + String formattedDate = DateFormat('yyyy-MM-dd').format(dateTime); + print( + 'Eventos para la fecha $formattedDate: ${mySelectedEvents[formattedDate]}'); + return mySelectedEvents[formattedDate] ?? []; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('Eventos')), + body: Column(children: [ + TableCalendar( + firstDay: DateTime.utc(2020, 1, 1), + lastDay: DateTime.utc(2030, 12, 31), + focusedDay: _focusedDay, + calendarFormat: _calendarFormat, + selectedDayPredicate: (day) { + return isSameDay(_selectedDay, day); + }, + onDaySelected: (selectedDay, focusedDay) { + if (!isSameDay(_selectedDay, selectedDay)) { + setState(() { + _selectedDay = selectedDay; + _focusedDay = focusedDay; + _selectedDate = selectedDay; + }); + + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => SafeArea( + child: Container( + height: MediaQuery.of(context).size.height * .9, + width: MediaQuery.of(context).size.width, + padding: EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Fecha seleccionada: ${selectedDay.toLocal()}'), + SizedBox(height: 10), + ..._listOfDayEvents(selectedDay).map((event) { + return ListTile( + title: Text(event['eventTitle']), + subtitle: Text(event['eventDescp']), + ); + }).toList(), + SizedBox(height: 10), + ElevatedButton( + onPressed: () => Navigator.pop(context), + child: Text('Cerrar'), + ), + ], + ), + ), + ), + ); + } + }, + onFormatChanged: (format) { + if (_calendarFormat != format) { + setState(() { + _calendarFormat = format; + }); + } + }, + onPageChanged: (focusedDay) { + _focusedDay = focusedDay; + }, + eventLoader: _listOfDayEvents, + ), + if (_selectedDate != null) + ..._listOfDayEvents(_selectedDate!).map((myEvents) => ListTile( + leading: const Icon( + Icons.done, + color: Colors.teal, + ), + title: Padding( + padding: const EdgeInsets.only(bottom: 8.0), + child: Text('Event Title: ${myEvents['eventTitle']}'), + ), + subtitle: Text('Description: ${myEvents['eventDescp']}'), + )) + ])); + } +} diff --git a/lib/screens/calendar_widget/modalCalendarWidget.dart b/lib/screens/calendar_widget/modalCalendarWidget.dart new file mode 100644 index 0000000..0b49fd6 --- /dev/null +++ b/lib/screens/calendar_widget/modalCalendarWidget.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:wolt_modal_sheet/wolt_modal_sheet.dart'; + + + +class Modalcalendarwidget extends StatelessWidget { + const Modalcalendarwidget({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Wolt Modal Bottom Sheet Sample'), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + WoltModalSheet.show( + context: context, + pageListBuilder: (bottomSheetContext) => [ + SliverWoltModalSheetPage( + mainContentSliversBuilder: (context) => [ + SliverList.builder( + itemBuilder: (context, index) { + return ListTile( + title: Text('Index is $index'), + onTap: Navigator.of(bottomSheetContext).pop, + ); + }, + ), + ], + ) + ], + ); + }, + label: const Text('Trigger Wolt Sheet'), + ), + ); + } + } diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index 799ed68..33ef085 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -4,6 +4,7 @@ import 'package:store_sqlite/controller/producto_controller.dart'; import 'package:store_sqlite/database/database.dart'; import 'package:store_sqlite/models/producto_model.dart'; import 'package:flutter_product_card/flutter_product_card.dart'; +import 'package:store_sqlite/screens/calendarScreen.dart'; import 'package:store_sqlite/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart'; import 'package:store_sqlite/screens/menuApp/widgetMenuApp/drawer.dart'; @@ -19,7 +20,7 @@ class _MenuappScreenvState extends State { final List _pages = [ Center(child: Pedidoslistawidget()), - Center(child: Text('Search Page')), + Center(child: TableBasicsExample()), Center(child: Text('Profile Page')), ]; @@ -100,6 +101,14 @@ class _MenuappScreenvState extends State { ], backgroundColor: const Color.fromARGB(131, 33, 31, 31), ), + floatingActionButton: FloatingActionButton( + onPressed: () {}, + child: Icon( + Icons.add, + ), + tooltip: 'Nuevo', + + ), body: _pages[_currentIndex], bottomNavigationBar: AnimatedBottomNavigation( height: 70, @@ -108,7 +117,7 @@ class _MenuappScreenvState extends State { icons: [ Icons.motorcycle, Icons.calendar_month, - Icons.person, + Icons.dashboard, ], currentIndex: _currentIndex, onTapChange: (index) { diff --git a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart index 6762582..b1df64f 100644 --- a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart +++ b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart @@ -15,9 +15,9 @@ class _PedidoslistawidgetState extends State { @override void initState() { pedidoController = PedidoController(); - print('////////////////////////////////////////////'); - pedidoController.mostrarPedidosConListaPedido(1); - print('////////////////////////////////////////////'); + // print('////////////////////////////////////////////'); + // pedidoController.mostrarPedidosConListaPedido(1); + // print('////////////////////////////////////////////'); super.initState(); } @@ -25,9 +25,9 @@ class _PedidoslistawidgetState extends State { switch (idStatus) { case 1: return Colors.green; // Si el idStatus es 1, el color será verde. - case 2: - return Colors.red; // Si el idStatus es 2, el color será rojo. case 3: + return Colors.red; // Si el idStatus es 2, el color será rojo. + case 2: return Colors.white; // Si el idStatus es 3, el color será blanco. default: return Colors @@ -42,12 +42,12 @@ class _PedidoslistawidgetState extends State { Icons.done, color: Colors.green, ); - case 2: + case 3: return const Icon( Icons.cancel, color: Colors.red, ); - case 3: + case 2: return const Icon( Icons.hourglass_empty, color: Colors.grey, diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 252c004..4b6159c 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,10 +5,14 @@ import FlutterMacOS import Foundation +import firebase_auth +import firebase_core import path_provider_foundation import sqflite_darwin func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 3b3d035..c8c47a6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "5534e701a2c505fed1f0799e652dd6ae23bd4d2c4cf797220e5ced5764a7c1c2" + url: "https://pub.dev" + source: hosted + version: "1.3.44" animated_botton_navigation: dependency: "direct main" description: @@ -97,6 +105,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: d453acec0d958ba0e25d41a9901b32cb77d1535766903dea7a61b2788c304596 + url: "https://pub.dev" + source: hosted + version: "5.3.1" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "78966c2ef774f5bf2a8381a307222867e9ece3509110500f7a138c115926aa65" + url: "https://pub.dev" + source: hosted + version: "7.4.7" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: "77ad3b252badedd3f08dfa21a4c7fe244be96c6da3a4067f253b13ea5d32424c" + url: "https://pub.dev" + source: hosted + version: "5.13.2" + firebase_core: + dependency: transitive + description: + name: firebase_core + sha256: "51dfe2fbf3a984787a2e7b8592f2f05c986bfedd6fdacea3f9e0a7beb334de96" + url: "https://pub.dev" + source: hosted + version: "3.6.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 + url: "https://pub.dev" + source: hosted + version: "2.18.1" flutter: dependency: "direct main" description: flutter @@ -131,6 +187,27 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" leak_tracker: dependency: transitive description: @@ -259,6 +336,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + simple_gesture_detector: + dependency: transitive + description: + name: simple_gesture_detector + sha256: ba2cd5af24ff20a0b8d609cec3f40e5b0744d2a71804a2616ae086b9c19d19a3 + url: "https://pub.dev" + source: hosted + version: "0.2.1" sky_engine: dependency: transitive description: flutter @@ -344,6 +429,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.3.0+3" + table_calendar: + dependency: "direct main" + description: + name: table_calendar + sha256: "4ca32b2fc919452c9974abd4c6ea611a63e33b9e4f0b8c38dba3ac1f4a6549d1" + url: "https://pub.dev" + source: hosted + version: "3.1.2" term_glyph: dependency: transitive description: @@ -360,6 +453,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" vector_math: dependency: transitive description: @@ -376,6 +477,22 @@ packages: url: "https://pub.dev" source: hosted version: "14.2.4" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + wolt_modal_sheet: + dependency: "direct main" + description: + name: wolt_modal_sheet + sha256: "2695dadd87e25604f0d9d64fae3696f4e053dcb7983a71e4494bb94b5bf3b67b" + url: "https://pub.dev" + source: hosted + version: "0.9.3" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index bf27eb1..a5af29a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,36 +28,28 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: - flutter: - sdk: flutter - sqflite: ^2.3.3+1 - path_provider: ^2.1.4 - flutter_product_card: ^0.0.7 animated_botton_navigation: ^0.0.7 animated_floating_buttons: ^0.0.2 - dropdown_button2: ^2.3.9 counter_button: ^1.0.1 - flutter_advanced_drawer: ^1.3.6 - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + dropdown_button2: ^2.3.9 + firebase_auth: ^5.3.1 + flutter: + sdk: flutter + flutter_advanced_drawer: ^1.3.6 + flutter_product_card: ^0.0.7 + path_provider: ^2.1.4 + sqflite: ^2.3.3+1 + table_calendar: ^3.1.2 + wolt_modal_sheet: ^0.9.3 dev_dependencies: + flutter_lints: ^4.0.0 flutter_test: sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^4.0.0 - # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec - # The following section is specific to Flutter packages. flutter: @@ -68,31 +60,28 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - - assets/img/ - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package + - assets/img/ + # - images/a_dot_ham.jpeg + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 8b6d468..d141b74 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,6 +6,12 @@ #include "generated_plugin_registrant.h" +#include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b93c4c3..29944d5 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + firebase_auth + firebase_core ) list(APPEND FLUTTER_FFI_PLUGIN_LIST From bf4f4f94ea9985fe238ec5f7469a8ec702a51b04 Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Sun, 20 Oct 2024 02:08:01 -0600 Subject: [PATCH 7/9] Vista carrito funcional, faltan pulir detalles y averiguar como mandar todos los valores --- lib/controller/carrito_controller.dart | 10 + lib/main.dart | 2 +- lib/screens/NuevoPedido/cardWidget.dart | 39 +++- lib/screens/carrito_screens.dart | 217 +++++++++++++++++- .../widgetMenuApp/PedidosListaWidget.dart | 1 + 5 files changed, 262 insertions(+), 7 deletions(-) diff --git a/lib/controller/carrito_controller.dart b/lib/controller/carrito_controller.dart index c589a15..59f0fa9 100644 --- a/lib/controller/carrito_controller.dart +++ b/lib/controller/carrito_controller.dart @@ -14,6 +14,16 @@ class CarritoController { var result = await con.query('id_carrito'); return result.map((carrito) => CarritoModel.fromMap(carrito)).toList(); } + Future>?> mostrarTodosLosCarritos() async { + var con = await _dataBase.database; + var result = await con.rawQuery(''' + SELECT * + FROM carrito c + inner join producto p on c.id_producto = p.id_producto + '''); // Aquí se pasa el parámetro + print(result); + return result; + } Future actualizarCarrito(String table, Map row) async { var con = await _dataBase.database; diff --git a/lib/main.dart b/lib/main.dart index 1ee4db2..beb9f39 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -14,7 +14,7 @@ class MyApp extends StatelessWidget { return MaterialApp( title: 'Material App', debugShowCheckedModeBanner: false, - theme: ThemeData.light(), + theme: ThemeData.dark(), home: const Menuappresponsivescreen( pantallaVerticalMobile: MenuappScreenv(), pantallaHorizontalMobile: MenuappScreenH()), diff --git a/lib/screens/NuevoPedido/cardWidget.dart b/lib/screens/NuevoPedido/cardWidget.dart index 2831f57..f804907 100644 --- a/lib/screens/NuevoPedido/cardWidget.dart +++ b/lib/screens/NuevoPedido/cardWidget.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_product_card/flutter_product_card.dart'; import 'package:counter_button/counter_button.dart'; +import 'package:store_sqlite/controller/carrito_controller.dart'; class Cardwidget extends StatefulWidget { final Map producto; @@ -11,17 +12,20 @@ class Cardwidget extends StatefulWidget { } class _CardwidgetState extends State { + CarritoController carritoController = CarritoController(); int _counterValue = 0; @override Widget build(BuildContext context) { double precio = widget.producto['precio']; + + double subtotal = 0; return Column( children: [ ProductCard( imageUrl: 'https://encrypted-tbn3.gstatic.com/shopping?q=tbn:ANd9GcQndSK7hvssofrM2uzv75NxVjrkAwH3RwyqWcBesUsmq1ipmkuljRr6x_SRbCKaBXvjTR9CKfAaEFtmUFw-69o52wgVMgk2hp8KDYr4FvKtQ8ZfKewgOW4gDQ&usqp=CAE4', - categoryName: '${widget.producto['categoria']}', + categoryName: '${widget.producto['id_producto']}', productName: '${widget.producto['producto']}', price: precio, currency: '\$', @@ -49,8 +53,37 @@ class _CardwidgetState extends State { // Otro SizedBox para el espacio entre CounterButton e IconButton SizedBox(height: 1), // Ajusta este valor también IconButton( - onPressed: () {}, - icon: Icon(Icons.add_shopping_cart_rounded), + onPressed: () { + print(_counterValue); + subtotal = precio * _counterValue; + if (subtotal > 0 && _counterValue > 0) { + // Validaciones + setState( + () { + carritoController.insertCarrito('carrito', { + 'id_producto': widget.producto['id_producto'], + 'cantidad': _counterValue, + 'subtotal': subtotal, + }); + _counterValue = 0; + + // Feedback al usuario + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Producto ${widget.producto['id_producto']} cantidad=${_counterValue} subtotal= ${subtotal}agregado al carrito')), + ); + }, + ); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Error: producto no válido ${widget.producto['id_producto']} o cantidad incorrecta $_counterValue')), + ); + } + }, + icon: const Icon(Icons.add_shopping_cart_rounded), ), ], ); diff --git a/lib/screens/carrito_screens.dart b/lib/screens/carrito_screens.dart index 074da1a..0474be8 100644 --- a/lib/screens/carrito_screens.dart +++ b/lib/screens/carrito_screens.dart @@ -1,4 +1,6 @@ +import 'package:counter_button/counter_button.dart'; import 'package:flutter/material.dart'; +import 'package:store_sqlite/controller/carrito_controller.dart'; class CarritoScreens extends StatefulWidget { const CarritoScreens({super.key}); @@ -8,10 +10,219 @@ class CarritoScreens extends StatefulWidget { } class _CarritoScreensState extends State { + CarritoController carritoController = CarritoController(); + List _counterValues = []; + final conNombreCliente = TextEditingController(); + final conTelefono = TextEditingController(); + final conColonia = TextEditingController(); + final conCalle = TextEditingController(); + final conNoExterior = TextEditingController(); + @override Widget build(BuildContext context) { - return Scaffold(appBar: AppBar( - title: Text('Carrito De Compras'), - ),); + return Scaffold( + appBar: AppBar( + title: const Text('Carrito'), + ), + floatingActionButton: FloatingActionButton( + child: const Icon(Icons.check), + onPressed: () { + // Mostrar modal para ingresar datos + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => SafeArea( + child: Container( + height: MediaQuery.of(context).size.height * .9, + width: MediaQuery.of(context).size.width, + padding: const EdgeInsets.all(16.0), + child: ListView( + shrinkWrap: true, + children: [ + const Padding( + padding: EdgeInsets.all(30.0), + child: Text('Datos Del Pedido'), + ), + TextFormField( + keyboardType: TextInputType.name, + controller: conNombreCliente, + decoration: const InputDecoration( + label: Text('Nombre Del Cliente'), + prefixIcon: Icon(Icons.person), + ), + ), + TextFormField( + keyboardType: TextInputType.number, + controller: conTelefono, + decoration: const InputDecoration( + label: Text('Número De Teléfono'), + prefixIcon: Icon(Icons.phone), + ), + ), + TextFormField( + keyboardType: TextInputType.name, + controller: conColonia, + decoration: const InputDecoration( + label: Text('Colonia'), + prefixIcon: Icon(Icons.add_location_alt_outlined), + ), + ), + TextFormField( + keyboardType: TextInputType.name, + controller: conCalle, + decoration: const InputDecoration( + label: Text('Calle'), + prefixIcon: Icon(Icons.streetview), + ), + ), + TextFormField( + keyboardType: TextInputType.number, + controller: conNoExterior, + decoration: const InputDecoration( + label: Text('Número Exterior'), + prefixIcon: Icon(Icons.numbers), + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: ElevatedButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cerrar'), + ), + ), + Padding( + padding: const EdgeInsets.all(15.0), + child: ElevatedButton( + onPressed: () { + // Acceder a todos los datos al presionar "Completado" + String nombreCliente = conNombreCliente.text; + String telefono = conTelefono.text; + String colonia = conColonia.text; + String calle = conCalle.text; + String noExterior = conNoExterior.text; + + // Puedes realizar cualquier acción con los datos aquí, + // como guardarlos en la base de datos o mostrarlos en consola. + print('Nombre del Cliente: $nombreCliente'); + print('Teléfono: $telefono'); + print('Colonia: $colonia'); + print('Calle: $calle'); + print('Número Exterior: $noExterior'); + print('Valores de los contadores: $_counterValues'); + + // Aquí podrías enviar los datos a tu base de datos usando carritoController + + // Cerrar el modal + Navigator.pop(context); + }, + child: Row( + children: const [ + Icon( + Icons.done_outline_outlined, + color: Colors.greenAccent, + ), + SizedBox(width: 8), + Text( + 'Completado', + style: TextStyle( + color: Colors.greenAccent, + fontSize: 16, + ), + ), + ], + ), + ), + ) + ], + ), + ], + ), + ), + ), + ); + }, + ), + body: FutureBuilder>?>( + future: carritoController.mostrarTodosLosCarritos(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Center( + child: CircularProgressIndicator(), + ); + } else if (snapshot.hasError) { + return Center( + child: Text(snapshot.error.toString()), + ); + } else if (snapshot.hasData && snapshot.data!.isNotEmpty) { + if (_counterValues.isEmpty) { + _counterValues = List.filled(snapshot.data!.length, 0); + } + List> carritos = snapshot.data!; + return ListView.builder( + itemCount: carritos.length, + itemBuilder: (context, index) { + var carrito = carritos[index]; + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: () {}, + child: Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: const Color.fromARGB(40, 75, 39, 39), + border: const Border( + left: BorderSide( + width: 4, + ), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${carrito['producto']}\n cantidad=${carrito['cantidad']}\n subtotal=${carrito['subtotal']}', + textAlign: TextAlign.left, + style: const TextStyle( + fontSize: 16, + ), + ), + CounterButton( + loading: false, + onChange: (int val) { + setState(() { + _counterValues[index] = val; + }); + }, + count: _counterValues[index], + countColor: Colors.purple, + buttonColor: Colors.purpleAccent, + progressColor: Colors.purpleAccent, + ), + ], + ), + ), + ], + ), + ), + ), + ); + }, + ); + } else { + return const Center( + child: Text('No hay pedidos disponibles'), + ); + } + }, + ), + ); } } diff --git a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart index b1df64f..7f3c07b 100644 --- a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart +++ b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart @@ -132,4 +132,5 @@ class _PedidoslistawidgetState extends State { ), ); } + } From 0df183465fe43047fdf231b488d9ffabf92bbd6b Mon Sep 17 00:00:00 2001 From: GokuPrograming Date: Sun, 20 Oct 2024 16:25:15 -0600 Subject: [PATCH 8/9] Correccion general --- lib/controller/carrito_controller.dart | 3 +- lib/controller/direccion_controller.dart | 2 +- lib/routes/rutes.dart | 6 +- .../{NuevoPedido.dart => Productos.dart} | 10 +-- .../cardWidget.dart | 0 lib/screens/carrito_screens.dart | 50 ++++++++++- .../dropDown_Municipio_Widget.dart | 85 +++++++++++++++++++ .../dropDownButtonListWidget.dart | 6 +- .../floatingButtonWidget.dart | 2 +- lib/screens/menuApp/MenuApp_screenV.dart | 9 +- 10 files changed, 151 insertions(+), 22 deletions(-) rename lib/screens/{NuevoPedido.dart => Productos.dart} (86%) rename lib/screens/{NuevoPedido => Productos}/cardWidget.dart (100%) create mode 100644 lib/screens/carrito_widgets/dropDown_Municipio_Widget.dart diff --git a/lib/controller/carrito_controller.dart b/lib/controller/carrito_controller.dart index 59f0fa9..ece397e 100644 --- a/lib/controller/carrito_controller.dart +++ b/lib/controller/carrito_controller.dart @@ -17,9 +17,10 @@ class CarritoController { Future>?> mostrarTodosLosCarritos() async { var con = await _dataBase.database; var result = await con.rawQuery(''' - SELECT * + SELECT *,sum(cantidad) as cantidad, sum(subtotal) as subtotal FROM carrito c inner join producto p on c.id_producto = p.id_producto + group by p.id_producto '''); // Aquí se pasa el parámetro print(result); return result; diff --git a/lib/controller/direccion_controller.dart b/lib/controller/direccion_controller.dart index 1ea4591..76b8662 100644 --- a/lib/controller/direccion_controller.dart +++ b/lib/controller/direccion_controller.dart @@ -4,7 +4,7 @@ import 'package:store_sqlite/models/direccion_model.dart'; class DireccionController { final TiendaDataBase _dataBase = TiendaDataBase(); - Future insertCategoria(String table, Map row) async { + Future insertDireccion(String table, Map row) async { final db = await _dataBase.database; return await db.insert(table, row); } diff --git a/lib/routes/rutes.dart b/lib/routes/rutes.dart index 6914bbf..249440a 100644 --- a/lib/routes/rutes.dart +++ b/lib/routes/rutes.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:store_sqlite/screens/NuevoPedido.dart'; +import 'package:store_sqlite/screens/Productos.dart'; import 'package:store_sqlite/screens/carrito_screens.dart'; import 'package:store_sqlite/screens/informacionPedido.dart'; import 'package:store_sqlite/screens/login/login_ScreenH.dart'; @@ -10,7 +10,7 @@ class AppRoutes { static const menuScreen = '/MenuScreen'; static const loginScreen = '/loginScreen'; static const informacionPedido = '/informacionPedido'; - static const nuevoPedido = '/crearPedido'; + static const productos = '/productos'; static const carrito = '/carrito'; static final routes = { //recibe una cadena , y un witget @@ -18,7 +18,7 @@ class AppRoutes { pantallaVerticalMobile: LoginScreenVertical(), pantallaHorizontalMobile: LoginScreenHorizontal()), informacionPedido: (context) => Informacionpedido(), - nuevoPedido: (context) => Nuevopedido(), + productos: (context) => Productos(), carrito: (contexto) => CarritoScreens(), }; } diff --git a/lib/screens/NuevoPedido.dart b/lib/screens/Productos.dart similarity index 86% rename from lib/screens/NuevoPedido.dart rename to lib/screens/Productos.dart index 322399e..de39816 100644 --- a/lib/screens/NuevoPedido.dart +++ b/lib/screens/Productos.dart @@ -1,16 +1,16 @@ import 'package:flutter/material.dart'; import 'package:store_sqlite/controller/producto_controller.dart'; import 'package:store_sqlite/models/producto_model.dart'; -import 'package:store_sqlite/screens/NuevoPedido/cardWidget.dart'; +import 'package:store_sqlite/screens/Productos/cardWidget.dart'; -class Nuevopedido extends StatefulWidget { - const Nuevopedido({super.key}); +class Productos extends StatefulWidget { + const Productos({super.key}); @override - State createState() => _NuevopedidoState(); + State createState() => _ProductosState(); } -class _NuevopedidoState extends State { +class _ProductosState extends State { late ProductoController productoController = ProductoController(); void initState() { super.initState(); diff --git a/lib/screens/NuevoPedido/cardWidget.dart b/lib/screens/Productos/cardWidget.dart similarity index 100% rename from lib/screens/NuevoPedido/cardWidget.dart rename to lib/screens/Productos/cardWidget.dart diff --git a/lib/screens/carrito_screens.dart b/lib/screens/carrito_screens.dart index 0474be8..686813f 100644 --- a/lib/screens/carrito_screens.dart +++ b/lib/screens/carrito_screens.dart @@ -1,6 +1,10 @@ import 'package:counter_button/counter_button.dart'; import 'package:flutter/material.dart'; import 'package:store_sqlite/controller/carrito_controller.dart'; +import 'package:store_sqlite/controller/direccion_controller.dart'; +import 'package:store_sqlite/controller/listaPedido_controller.dart'; +import 'package:store_sqlite/models/lista_pedido_model.dart'; +import 'package:store_sqlite/screens/carrito_widgets/dropDown_Municipio_Widget.dart'; class CarritoScreens extends StatefulWidget { const CarritoScreens({super.key}); @@ -83,6 +87,12 @@ class _CarritoScreensState extends State { prefixIcon: Icon(Icons.numbers), ), ), + const Row( + children: [ + Text('Municipio'), + DropdownMunicipioWidget(), + ], + ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -97,25 +107,32 @@ class _CarritoScreensState extends State { padding: const EdgeInsets.all(15.0), child: ElevatedButton( onPressed: () { - // Acceder a todos los datos al presionar "Completado" + // Acceder a los datos al presionar "Completado" String nombreCliente = conNombreCliente.text; String telefono = conTelefono.text; String colonia = conColonia.text; String calle = conCalle.text; String noExterior = conNoExterior.text; - // Puedes realizar cualquier acción con los datos aquí, - // como guardarlos en la base de datos o mostrarlos en consola. + // Aquí accedes a los valores de los contadores y haces lo necesario print('Nombre del Cliente: $nombreCliente'); print('Teléfono: $telefono'); print('Colonia: $colonia'); print('Calle: $calle'); print('Número Exterior: $noExterior'); - print('Valores de los contadores: $_counterValues'); + print( + 'Valores de los contadores: $_counterValues'); + + // Puedes procesar los datos aquí, por ejemplo, guardarlos en tu base de datos + // usando carritoController. + // Cerrar el modal // Aquí podrías enviar los datos a tu base de datos usando carritoController + // ingresarDireccion(nombreCliente, telefono, + // colonia, calle, noExterior); // Cerrar el modal + Navigator.pop(context); }, child: Row( @@ -225,4 +242,29 @@ class _CarritoScreensState extends State { ), ); } + + void ingresarDireccion(String nombreCliente, String NumeroTel, String Colonia, + String Calle, String NumExterior) { + print('se ingresaron los datos'); + + try { + + } catch (e) { + + } + DireccionController direccionController = DireccionController(); + direccionController.insertDireccion('direccion', { + 'Id_comunidad': 1, + 'calle': '${Calle}', + 'no_exterior': '${NumExterior}', + 'colonia': '$Colonia', + 'no_interior': '', + 'telefono': '${NumeroTel}', + 'cliente_nombre': '$nombreCliente' + }); + print('pasando los valores a las tablas'); + ListapedidoController listapedidoController = ListapedidoController(); + listapedidoController.insertarListaPedido('lista_pedido', + {'id_pedido': '', 'id_producto': '', 'cantidad': '', 'subtotal': ''}); + } } diff --git a/lib/screens/carrito_widgets/dropDown_Municipio_Widget.dart b/lib/screens/carrito_widgets/dropDown_Municipio_Widget.dart new file mode 100644 index 0000000..4e8d99e --- /dev/null +++ b/lib/screens/carrito_widgets/dropDown_Municipio_Widget.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; +import 'package:store_sqlite/controller/municipio_controller.dart'; +import 'package:store_sqlite/models/municipio_model.dart'; + +class DropdownMunicipioWidget extends StatefulWidget { + const DropdownMunicipioWidget({super.key}); + + @override + State createState() => + _DropdownMunicipioWidgetState(); +} + +class _DropdownMunicipioWidgetState extends State { + late MunicipioController municipioController = MunicipioController(); + List municipios = []; + ValueNotifier selectedMunicipioNotifier = ValueNotifier(null); + + @override + void initState() { + super.initState(); + obtenerMunicipios(); + } + + void obtenerMunicipios() async { + List? fetchedMunicipios = await municipioController.mostrarTodosLosMunicipios(); + if (fetchedMunicipios != null) { + setState(() { + municipios = fetchedMunicipios; + }); + } else { + print('No se encontraron municipios.'); + } + } + + @override + Widget build(BuildContext context) { + return Container( + width: 200, // Ajusta el ancho del Container + child: ValueListenableBuilder( + valueListenable: selectedMunicipioNotifier, + builder: (context, selectedMunicipio, child) { + return DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Text( + 'Seleccione un municipio', + style: TextStyle( + fontSize: 14, + color: Theme.of(context).hintColor, + ), + ), + items: municipios + .map((municipio) => DropdownMenuItem( + value: municipio, + child: Text( + '${municipio.municipio}', + style: const TextStyle( + fontSize: 14, + ), + ), + )) + .toList(), + value: selectedMunicipio, + onChanged: (MunicipioModel? value) { + selectedMunicipioNotifier.value = value; + if (value != null) { + print('ID: ${value.id_municipio}, Municipio: ${value.municipio}'); + } + }, + buttonStyleData: const ButtonStyleData( + padding: EdgeInsets.symmetric(horizontal: 16), + height: 40, + width: 160, // Ajusta el ancho del DropdownButton2 + ), + menuItemStyleData: const MenuItemStyleData( + height: 40, + ), + ), + ); + }, + ), + ); + } +} diff --git a/lib/screens/infromacionPedido/dropDownButtonListWidget.dart b/lib/screens/infromacionPedido/dropDownButtonListWidget.dart index f7dcf87..25707d0 100644 --- a/lib/screens/infromacionPedido/dropDownButtonListWidget.dart +++ b/lib/screens/infromacionPedido/dropDownButtonListWidget.dart @@ -5,8 +5,8 @@ import 'package:store_sqlite/models/lista_pedido_model.dart'; import 'package:store_sqlite/models/status_model.dart'; class Dropdownbuttonlistwidget extends StatefulWidget { - const Dropdownbuttonlistwidget(this.id_status, {super.key}); - final int? id_status; + const Dropdownbuttonlistwidget( {super.key}); + // Constructor modificado @override @@ -48,7 +48,7 @@ class _DropdownbuttonlistwidgetState extends State { child: DropdownButton2( isExpanded: true, hint: Text( - '${widget.id_status}', + '', style: TextStyle( fontSize: 14, color: Theme.of(context).hintColor, diff --git a/lib/screens/infromacionPedido/floatingButtonWidget.dart b/lib/screens/infromacionPedido/floatingButtonWidget.dart index b7b1f91..799f6eb 100644 --- a/lib/screens/infromacionPedido/floatingButtonWidget.dart +++ b/lib/screens/infromacionPedido/floatingButtonWidget.dart @@ -16,7 +16,7 @@ class _FloatingbuttonwidgetState extends State { return Container( child: FloatingActionButton( onPressed: () { - Navigator.pushNamed(context, '/crearPedido'); + Navigator.pushNamed(context, '/productos'); }, heroTag: "new", tooltip: 'First button', diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index 33ef085..6f54d93 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -94,20 +94,21 @@ class _MenuappScreenvState extends State { actions: [ IconButton( onPressed: () { - Navigator.pushNamed(context, '/crearPedido'); + Navigator.pushNamed(context, '/carrito'); }, - icon: Icon(Icons.add), + icon: Icon(Icons.shopping_cart), ), ], backgroundColor: const Color.fromARGB(131, 33, 31, 31), ), floatingActionButton: FloatingActionButton( - onPressed: () {}, + onPressed: () { + Navigator.pushNamed(context, '/productos'); + }, child: Icon( Icons.add, ), tooltip: 'Nuevo', - ), body: _pages[_currentIndex], bottomNavigationBar: AnimatedBottomNavigation( From 112eb14fd3b02f7da07d388152976f1d72741887 Mon Sep 17 00:00:00 2001 From: Jesus Salinas <89615727+JSalinas13@users.noreply.github.com> Date: Sun, 20 Oct 2024 17:41:53 -0600 Subject: [PATCH 9/9] Se agregaron las pantallas de historial, pendientes y completadas --- lib/controller/pedido_controller.dart | 30 +++++++++++++++++-- lib/database/database.dart | 2 +- lib/screens/menuApp/MenuApp_screenV.dart | 19 +++++++++--- .../widgetMenuApp/PedidosListaWidget.dart | 7 +++-- pubspec.lock | 4 +-- 5 files changed, 49 insertions(+), 13 deletions(-) diff --git a/lib/controller/pedido_controller.dart b/lib/controller/pedido_controller.dart index f131a09..7e464ce 100644 --- a/lib/controller/pedido_controller.dart +++ b/lib/controller/pedido_controller.dart @@ -9,10 +9,34 @@ class PedidoController { return await db.insert(table, row); } - Future?> mostrarTodosLosPedidos() async { + Future?> mostrarTodosLosPedidos(int opc) async { var con = await _dataBase.database; - var result = await con.query('pedido'); - return result.map((pedido) => PedidoModel.fromMap(pedido)).toList(); + + // Definimos el tipo de result para mayor claridad. + List> result; + + switch (opc) { + case 0: + result = + await con.query('pedido', where: 'id_status = ?', whereArgs: [2]); + break; + case 1: + result = await con.query('pedido'); + break; + case 2: + result = + await con.query('pedido', where: 'id_status = ?', whereArgs: [1]); + break; + default: + return []; // Si opc no coincide con ninguno, retornamos una lista vacía. + } + + // Verificamos si result está vacío o nulo antes de mapear. + if (result.isNotEmpty) { + return result.map((pedido) => PedidoModel.fromMap(pedido)).toList(); + } else { + return []; + } } Future actualizarPedido(String table, Map row) async { diff --git a/lib/database/database.dart b/lib/database/database.dart index ab4f431..f468f06 100644 --- a/lib/database/database.dart +++ b/lib/database/database.dart @@ -133,7 +133,7 @@ VALUES db.execute(query11); String query12 = ''' - Insert into status(status)values('completado'),('En Proceso'),('cancelado') + Insert into status(status)values('completado'),('pendiente'),('cancelado') '''; db.execute(query12); diff --git a/lib/screens/menuApp/MenuApp_screenV.dart b/lib/screens/menuApp/MenuApp_screenV.dart index 6f54d93..d5a4f9a 100644 --- a/lib/screens/menuApp/MenuApp_screenV.dart +++ b/lib/screens/menuApp/MenuApp_screenV.dart @@ -19,9 +19,19 @@ class _MenuappScreenvState extends State { int _currentIndex = 0; final List _pages = [ - Center(child: Pedidoslistawidget()), + Center( + child: Pedidoslistawidget( + opc: 0, + )), + Center( + child: Pedidoslistawidget( + opc: 1, + )), Center(child: TableBasicsExample()), - Center(child: Text('Profile Page')), + Center( + child: Pedidoslistawidget( + opc: 2, + )), ]; @override @@ -116,9 +126,10 @@ class _MenuappScreenvState extends State { indicatorSpaceBotton: 25, selectedColor: Colors.black, icons: [ - Icons.motorcycle, + Icons.pending_outlined, + Icons.schedule, Icons.calendar_month, - Icons.dashboard, + Icons.task_alt ], currentIndex: _currentIndex, onTapChange: (index) { diff --git a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart index 7f3c07b..e36d558 100644 --- a/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart +++ b/lib/screens/menuApp/widgetMenuApp/PedidosListaWidget.dart @@ -3,7 +3,9 @@ import 'package:store_sqlite/controller/pedido_controller.dart'; import 'package:store_sqlite/models/pedido_model.dart'; class Pedidoslistawidget extends StatefulWidget { - const Pedidoslistawidget({super.key}); + final int opc; + + const Pedidoslistawidget({super.key, required this.opc}); @override State createState() => _PedidoslistawidgetState(); @@ -61,7 +63,7 @@ class _PedidoslistawidgetState extends State { var LargoContenedorList = MediaQuery.of(context).size.width * .1; return Scaffold( body: FutureBuilder( - future: pedidoController.mostrarTodosLosPedidos(), + future: pedidoController.mostrarTodosLosPedidos(widget.opc), builder: (context, AsyncSnapshot?> snapshot) { if (snapshot.hasData) { return ListView.builder( @@ -132,5 +134,4 @@ class _PedidoslistawidgetState extends State { ), ); } - } diff --git a/pubspec.lock b/pubspec.lock index c8c47a6..2a858ca 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -473,10 +473,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.4" + version: "14.2.5" web: dependency: transitive description: