|
@@ -1,9 +1,14 @@
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
|
-class ProductScreen extends StatelessWidget {
|
|
|
+class ProductScreen extends StatefulWidget {
|
|
|
const ProductScreen({super.key});
|
|
|
|
|
|
@override
|
|
|
+ State<ProductScreen> createState() => _ProductScreenState();
|
|
|
+}
|
|
|
+
|
|
|
+class _ProductScreenState extends State<ProductScreen> {
|
|
|
+ @override
|
|
|
Widget build(BuildContext context) {
|
|
|
return Scaffold(
|
|
|
appBar: AppBar(
|
|
@@ -19,83 +24,458 @@ class ProductScreen extends StatelessWidget {
|
|
|
],
|
|
|
),
|
|
|
backgroundColor: Colors.white,
|
|
|
- body: Column(
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
- children: [
|
|
|
- Stack(children: [
|
|
|
- Positioned(
|
|
|
- top: 20,
|
|
|
- left: 20,
|
|
|
- child: IconButton(
|
|
|
- icon: const Icon(
|
|
|
- Icons.arrow_back,
|
|
|
- color: Colors.white,
|
|
|
+ body: SingleChildScrollView(
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Stack(children: [
|
|
|
+ Positioned(
|
|
|
+ top: 20,
|
|
|
+ left: 20,
|
|
|
+ child: IconButton(
|
|
|
+ icon: const Icon(
|
|
|
+ Icons.arrow_back,
|
|
|
+ color: Colors.white,
|
|
|
+ semanticLabel: "Regresar",
|
|
|
+ ),
|
|
|
+ onPressed: () => Navigator.pop(context),
|
|
|
),
|
|
|
- onPressed: () => Navigator.pop(context),
|
|
|
+ ),
|
|
|
+ Container(
|
|
|
+ height: 350,
|
|
|
+ width: double.infinity,
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: const BorderRadius.only(
|
|
|
+ topLeft: Radius.circular(25),
|
|
|
+ topRight: Radius.circular(25),
|
|
|
+ ),
|
|
|
+ image: DecorationImage(
|
|
|
+ image: NetworkImage(
|
|
|
+ 'https://cdn.pixabay.com/photo/2023/04/02/21/38/sandwich-7895477_1280.jpg'),
|
|
|
+ fit: BoxFit.cover,
|
|
|
+ colorFilter: ColorFilter.mode(
|
|
|
+ Colors.black.withOpacity(0.3),
|
|
|
+ BlendMode.darken,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ ]),
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ const Padding(
|
|
|
+ padding: EdgeInsets.symmetric(horizontal: 20),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ Text(
|
|
|
+ 'Sandwich de pollo',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 44,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ Text(
|
|
|
+ 'Queso, Lechuga, tomate, cebolla, pepinillo, mayonesa, ketchup y moztaza. Acompañado de Papas y Soda',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 26,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ Text(
|
|
|
+ 'MXN 115.00',
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 36,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ Divider(
|
|
|
+ height: 2,
|
|
|
+ ),
|
|
|
+ SizedBox(height: 10),
|
|
|
+ ToppingsView(),
|
|
|
+ ],
|
|
|
),
|
|
|
),
|
|
|
- Container(
|
|
|
- height: 350,
|
|
|
- width: double.infinity,
|
|
|
- decoration: BoxDecoration(
|
|
|
- borderRadius: const BorderRadius.only(
|
|
|
- topLeft: Radius.circular(25),
|
|
|
- topRight: Radius.circular(25),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+class ToppingsView extends StatefulWidget {
|
|
|
+ const ToppingsView({super.key});
|
|
|
+
|
|
|
+ @override
|
|
|
+ State<ToppingsView> createState() => _ToppingsViewState();
|
|
|
+}
|
|
|
+
|
|
|
+class _ToppingsViewState extends State<ToppingsView> {
|
|
|
+ // Estado para controlar la expansión de cada sección
|
|
|
+ bool isToppingsExpanded = false;
|
|
|
+ bool isRefrescoExpanded = false;
|
|
|
+ bool isCoccionExpanded = false;
|
|
|
+ bool isQuesoExpanded = true;
|
|
|
+
|
|
|
+ // Estado para la selección de queso
|
|
|
+ bool isQuesoSelected = false;
|
|
|
+
|
|
|
+ // Opciones para los dropdowns (como ejemplo)
|
|
|
+ final List<String> toppingsOptions = [
|
|
|
+ 'Cebolla',
|
|
|
+ 'Pepperoni',
|
|
|
+ 'Champiñones',
|
|
|
+ 'Tocino',
|
|
|
+ 'Pimiento',
|
|
|
+ 'Jalapeño'
|
|
|
+ ];
|
|
|
+ final List<String> refrescoOptions = [
|
|
|
+ 'Coca-Cola',
|
|
|
+ 'Sprite',
|
|
|
+ 'Fanta',
|
|
|
+ 'Agua mineral'
|
|
|
+ ];
|
|
|
+ final List<String> coccionOptions = [
|
|
|
+ 'Término medio',
|
|
|
+ 'Tres cuartos',
|
|
|
+ 'Bien cocido'
|
|
|
+ ];
|
|
|
+
|
|
|
+ // Selecciones actuales
|
|
|
+ List<String> selectedToppings = [];
|
|
|
+ String? selectedRefresco;
|
|
|
+ String? selectedCoccion;
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget build(BuildContext context) {
|
|
|
+ return SingleChildScrollView(
|
|
|
+ child: Container(
|
|
|
+ color: Colors.white,
|
|
|
+ child: Padding(
|
|
|
+ padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ // 1. Dropdown de Toppings
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "SELECCIONA 3 TOPPINGS",
|
|
|
+ subtitle: "Seleccione hasta 3 opciones",
|
|
|
+ isExpanded: isToppingsExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isToppingsExpanded = !isToppingsExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isToppingsExpanded ? _buildToppingsContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 2. Dropdown de Refresco
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "ELIGE UN REFRESCO SIN COSTO",
|
|
|
+ subtitle: "Seleccione hasta 1 opcion",
|
|
|
+ isExpanded: isRefrescoExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isRefrescoExpanded = !isRefrescoExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isRefrescoExpanded ? _buildRefrescoContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 3. Dropdown de Término de Cocción
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "Elige el término de cocción",
|
|
|
+ subtitle: "Seleccione mínimo 1 opciones",
|
|
|
+ isExpanded: isCoccionExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isCoccionExpanded = !isCoccionExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isCoccionExpanded ? _buildCoccionContent() : null,
|
|
|
+ showObligatorio: true,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 4. Dropdown de Queso amarillo
|
|
|
+ _buildDropdownSection(
|
|
|
+ title: "Queso amarillo para papas",
|
|
|
+ subtitle: null, // Sin subtítulo
|
|
|
+ isExpanded: isQuesoExpanded,
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isQuesoExpanded = !isQuesoExpanded;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ content: isQuesoExpanded ? _buildQuesoContent() : null,
|
|
|
+ ),
|
|
|
+ const Divider(color: Colors.grey),
|
|
|
+
|
|
|
+ // 5. Sección de Comentarios
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ const Text(
|
|
|
+ "Comentarios",
|
|
|
+ style: TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Container(
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(8),
|
|
|
+ border: Border.all(color: Colors.grey),
|
|
|
),
|
|
|
- image: DecorationImage(
|
|
|
- image: NetworkImage(
|
|
|
- 'https://cdn.pixabay.com/photo/2023/04/02/21/38/sandwich-7895477_1280.jpg'),
|
|
|
- fit: BoxFit.cover,
|
|
|
- colorFilter: ColorFilter.mode(
|
|
|
- Colors.black.withOpacity(0.3),
|
|
|
- BlendMode.darken,
|
|
|
+ height: 80,
|
|
|
+ child: const TextField(
|
|
|
+ style: TextStyle(color: Colors.black),
|
|
|
+ maxLines: 3,
|
|
|
+ decoration: InputDecoration(
|
|
|
+ contentPadding: EdgeInsets.all(12),
|
|
|
+ border: InputBorder.none,
|
|
|
+ hintText: "Agrega instrucciones especiales...",
|
|
|
+ hintStyle: TextStyle(color: Colors.grey),
|
|
|
),
|
|
|
),
|
|
|
),
|
|
|
- )
|
|
|
- ]),
|
|
|
- const SizedBox(height: 20),
|
|
|
- const Padding(
|
|
|
- padding: EdgeInsets.symmetric(horizontal: 20),
|
|
|
- child: Column(
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
- children: [
|
|
|
- Text(
|
|
|
- 'Sandwich de pollo',
|
|
|
+
|
|
|
+ // 6. Precio
|
|
|
+ const SizedBox(height: 30),
|
|
|
+ const Center(
|
|
|
+ child: Text(
|
|
|
+ "Precio: MXN 115.00",
|
|
|
style: TextStyle(
|
|
|
- color: Colors.black,
|
|
|
- fontSize: 44,
|
|
|
+ color: Colors.white,
|
|
|
+ fontSize: 24,
|
|
|
fontWeight: FontWeight.bold,
|
|
|
),
|
|
|
),
|
|
|
- SizedBox(height: 10),
|
|
|
- Text(
|
|
|
- 'Descripcion del producto',
|
|
|
- style: TextStyle(
|
|
|
+ ),
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Construye la estructura base de cada dropdown
|
|
|
+ Widget _buildDropdownSection({
|
|
|
+ required String title,
|
|
|
+ String? subtitle,
|
|
|
+ required bool isExpanded,
|
|
|
+ required VoidCallback onTap,
|
|
|
+ Widget? content,
|
|
|
+ bool showObligatorio = false,
|
|
|
+ }) {
|
|
|
+ return SingleChildScrollView(
|
|
|
+ child: Column(
|
|
|
+ children: [
|
|
|
+ Row(
|
|
|
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
+ children: [
|
|
|
+ Expanded(
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ const SizedBox(height: 16),
|
|
|
+ Text(
|
|
|
+ title,
|
|
|
+ style: const TextStyle(
|
|
|
+ color: Colors.black,
|
|
|
+ fontSize: 20,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ if (subtitle != null) ...[
|
|
|
+ const SizedBox(height: 4),
|
|
|
+ Text(
|
|
|
+ subtitle,
|
|
|
+ style: const TextStyle(
|
|
|
+ color: Colors.grey,
|
|
|
+ fontSize: 16,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ if (subtitle == null) const SizedBox(height: 16),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ if (showObligatorio) ...[
|
|
|
+ Container(
|
|
|
+ padding:
|
|
|
+ const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ borderRadius: BorderRadius.circular(20),
|
|
|
+ border: Border.all(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ child: const Text(
|
|
|
+ "Obligatorio",
|
|
|
+ style: TextStyle(color: Colors.grey),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 10),
|
|
|
+ ],
|
|
|
+ GestureDetector(
|
|
|
+ onTap: onTap,
|
|
|
+ child: Container(
|
|
|
+ width: 40,
|
|
|
+ height: 40,
|
|
|
+ decoration: const BoxDecoration(
|
|
|
+ color: Color(0xFF333333),
|
|
|
+ shape: BoxShape.circle,
|
|
|
+ ),
|
|
|
+ child: Icon(
|
|
|
+ isExpanded
|
|
|
+ ? Icons.keyboard_arrow_up
|
|
|
+ : Icons.keyboard_arrow_down,
|
|
|
color: Colors.black,
|
|
|
- fontSize: 36,
|
|
|
),
|
|
|
),
|
|
|
- SizedBox(height: 10),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ if (content != null) content,
|
|
|
+ const SizedBox(height: 8),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ Widget _buildToppingsContent() {
|
|
|
+ return Column(
|
|
|
+ children: toppingsOptions.map((topping) {
|
|
|
+ final isSelected = selectedToppings.contains(topping);
|
|
|
+ return CheckboxListTile(
|
|
|
+ contentPadding: const EdgeInsets.symmetric(horizontal: 8),
|
|
|
+ title: Text(
|
|
|
+ topping,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: isSelected,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ checkColor: Colors.black,
|
|
|
+ side: const BorderSide(color: Colors.black),
|
|
|
+ onChanged: (bool? value) {
|
|
|
+ setState(() {
|
|
|
+ if (value == true) {
|
|
|
+ if (selectedToppings.length < 3) {
|
|
|
+ selectedToppings.add(topping);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ selectedToppings.remove(topping);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Refresco
|
|
|
+ Widget _buildRefrescoContent() {
|
|
|
+ return Column(
|
|
|
+ children: refrescoOptions.map((refresco) {
|
|
|
+ return RadioListTile<String>(
|
|
|
+ title: Text(
|
|
|
+ refresco,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: refresco,
|
|
|
+ groupValue: selectedRefresco,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
|
|
+ return Colors.black;
|
|
|
+ }),
|
|
|
+ onChanged: (String? value) {
|
|
|
+ setState(() {
|
|
|
+ selectedRefresco = value;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Cocción
|
|
|
+ Widget _buildCoccionContent() {
|
|
|
+ return Column(
|
|
|
+ children: coccionOptions.map((coccion) {
|
|
|
+ return RadioListTile<String>(
|
|
|
+ title: Text(
|
|
|
+ coccion,
|
|
|
+ style: const TextStyle(color: Colors.black),
|
|
|
+ ),
|
|
|
+ value: coccion,
|
|
|
+ groupValue: selectedCoccion,
|
|
|
+ activeColor: Colors.blue,
|
|
|
+ fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
|
|
+ return Colors.black;
|
|
|
+ }),
|
|
|
+ onChanged: (String? value) {
|
|
|
+ setState(() {
|
|
|
+ selectedCoccion = value;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ );
|
|
|
+ }).toList(),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ // Contenido del dropdown de Queso
|
|
|
+ Widget _buildQuesoContent() {
|
|
|
+ return Container(
|
|
|
+ margin: const EdgeInsets.only(top: 8, bottom: 8),
|
|
|
+ padding: const EdgeInsets.symmetric(vertical: 8),
|
|
|
+ child: InkWell(
|
|
|
+ onTap: () {
|
|
|
+ setState(() {
|
|
|
+ isQuesoSelected = !isQuesoSelected;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ child: Row(
|
|
|
+ children: [
|
|
|
+ Container(
|
|
|
+ width: 24,
|
|
|
+ height: 24,
|
|
|
+ margin: const EdgeInsets.only(left: 12),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ border: Border.all(color: Colors.black),
|
|
|
+ ),
|
|
|
+ child: isQuesoSelected
|
|
|
+ ? const Icon(Icons.check, color: Colors.black, size: 20)
|
|
|
+ : null,
|
|
|
+ ),
|
|
|
+ const SizedBox(width: 16),
|
|
|
+ const Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
Text(
|
|
|
- 'Precio: \$ 10.00',
|
|
|
+ "Queso amarillo",
|
|
|
style: TextStyle(
|
|
|
color: Colors.black,
|
|
|
- fontSize: 36,
|
|
|
+ fontSize: 16,
|
|
|
+ fontWeight: FontWeight.bold,
|
|
|
),
|
|
|
),
|
|
|
- SizedBox(height: 10),
|
|
|
Text(
|
|
|
- 'Existencia: 10',
|
|
|
+ "+ MXN 5.00",
|
|
|
style: TextStyle(
|
|
|
color: Colors.black,
|
|
|
- fontSize: 36,
|
|
|
+ fontSize: 16,
|
|
|
),
|
|
|
),
|
|
|
],
|
|
|
),
|
|
|
- ),
|
|
|
- ],
|
|
|
+ ],
|
|
|
+ ),
|
|
|
),
|
|
|
);
|
|
|
}
|