gp_design 0.0.5 copy "gp_design: ^0.0.5" to clipboard
gp_design: ^0.0.5 copied to clipboard

Colección de componentes, temas, tokens visuales y utilidades responsivas para construir apps Flutter consistentes con el sistema de diseño GP.

example/lib/main.dart

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:gp_design/gp_design.dart';
import 'package:gp_design/network.dart';

void main() {
  runApp(const DemoApp());
}

class DemoApp extends StatelessWidget {
  const DemoApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Builder(
      builder: (context) => MaterialApp(
        title: 'GP Design Demo',
        theme: GpTheme.light(context),
        darkTheme: GpTheme.dark(context),
        themeMode: ThemeMode.system,
        home: const DemoHome(),
      ),
    );
  }
}

class DemoHome extends StatefulWidget {
  const DemoHome({super.key});

  @override
  State<DemoHome> createState() => _DemoHomeState();
}

class _DemoHomeState extends State<DemoHome> {
  final Dio _dio = Dio(BaseOptions(baseUrl: 'https://httpbin.org'))
    ..interceptors.addAll([
      AuthInterceptor(() async => Future.value('demo-token')),
      ErrorInterceptor(),
    ]);

  final List<List<Object?>> _userRows = [
    ['u_001', 'Ana Perez', 'ana.perez@empresa.com', 'Activo'],
    ['u_002', 'Carlos Medina', 'carlos.medina@empresa.com', 'Pendiente'],
    ['u_003', 'Luisa Gomez', 'luisa.gomez@empresa.com', 'Suspendido'],
    ['u_004', 'Javier Rojas', 'javier.rojas@empresa.com', 'Activo'],
    ['u_005', 'Mariana Silva', 'mariana.silva@empresa.com', 'Activo'],
    ['u_006', 'Diego Torres', 'diego.torres@empresa.com', 'Pendiente'],
    ['u_007', 'Sara Ibarra', 'sara.ibarra@empresa.com', 'Activo'],
    ['u_008', 'Ramon Ruiz', 'ramon.ruiz@empresa.com', 'Suspendido'],
    ['u_009', 'Camila Nunez', 'camila.nunez@empresa.com', 'Activo'],
    ['u_010', 'Pablo Reyes', 'pablo.reyes@empresa.com', 'Pendiente'],
    ['u_011', 'Daniela Soto', 'daniela.soto@empresa.com', 'Activo'],
    ['u_012', 'Leo Vargas', 'leo.vargas@empresa.com', 'Suspendido'],
    ['u_013', 'Marta Rios', 'marta.rios@empresa.com', 'Activo'],
    ['u_014', 'Nicolas Paredes', 'nicolas.paredes@empresa.com', 'Pendiente'],
    ['u_015', 'Olivia Diaz', 'olivia.diaz@empresa.com', 'Activo'],
    ['u_016', 'Renato Castro', 'renato.castro@empresa.com', 'Suspendido'],
    ['u_017', 'Paula Flores', 'paula.flores@empresa.com', 'Activo'],
    ['u_018', 'Sergio Mora', 'sergio.mora@empresa.com', 'Pendiente'],
    ['u_019', 'Tamara Cruz', 'tamara.cruz@empresa.com', 'Activo'],
    ['u_020', 'Victor Salas', 'victor.salas@empresa.com', 'Suspendido'],
    ['u_021', 'Wendy Silva', 'wendy.silva@empresa.com', 'Activo'],
    ['u_022', 'Ximena Ramos', 'ximena.ramos@empresa.com', 'Pendiente'],
    ['u_023', 'Yago Ortiz', 'yago.ortiz@empresa.com', 'Activo'],
    ['u_024', 'Zoe Marin', 'zoe.marin@empresa.com', 'Suspendido'],
  ];

  int _tablePage = 1;
  final int _pageSize = 5;

  bool _loading = false;
  String? _responseMessage;
  final GlobalKey _pinKey = GlobalKey();

  Future<void> _simulateRequest() async {
    setState(() {
      _loading = true;
      _responseMessage = null;
    });

    try {
      await _dio.get('/status/500');
      if (!mounted) return;
      setState(() => _responseMessage = 'Petición simulada con token Bearer.');
    } on DioException catch (error) {
      final customError = error.error;
      if (!mounted) return;
      setState(() {
        _responseMessage = customError is GpException
            ? customError.message
            : (error.message ?? 'Error desconocido');
      });
    } finally {
      if (mounted) {
        setState(() => _loading = false);
      }
    }
  }

  List<List<Object?>> _currentPageRows() {
    final start = (_tablePage - 1) * _pageSize;
    final end = (start + _pageSize).clamp(0, _userRows.length);
    return _userRows.sublist(start, end);
  }

  Widget _statusBadge(String status) {
    final colors = Theme.of(context).colorScheme;
    Color background;
    Color textColor;
    switch (status) {
      case 'Activo':
        background = colors.primary.withValues(alpha: 0.12);
        textColor = colors.primary;
        break;
      case 'Pendiente':
        background = colors.tertiary.withValues(alpha: 0.15);
        textColor = colors.tertiary;
        break;
      case 'Suspendido':
      default:
        background = colors.error.withValues(alpha: 0.12);
        textColor = colors.error;
    }

    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
      decoration: BoxDecoration(
        color: background,
        borderRadius: BorderRadius.circular(999),
      ),
      child: GpText(
        text: status,
        style: Theme.of(context).textTheme.labelSmall?.copyWith(
          color: textColor,
          fontWeight: FontWeight.w600,
        ),
        selectable: false,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Scaffold(
      appBar: const GpAppBar(title: 'GP Design Demo'),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          GpText(
            text: 'Componentes principales',
            style: theme.textTheme.titleLarge,
          ),
          const SizedBox(height: 12),
          GpButton(
            text: 'Mostrar diálogo',
            onPressed: () => showDialog<void>(
              context: context,
              builder: (_) => Dialog(
                child: GpAlertDialog(
                  title: '¡Hola!',
                  message: 'Este es el diálogo de GP listo para usarse.',
                  onPressed: () {},
                ),
              ),
            ),
          ),
          const SizedBox(height: 24),
          GpRow(
            gutter: 16,
            children: const [
              GpCol(
                span: 4,
                child: Card(
                  child: Padding(
                    padding: EdgeInsets.all(16),
                    child: GpText(text: 'Span 4/12'),
                  ),
                ),
              ),
              GpCol(
                span: 4,
                child: Card(
                  child: Padding(
                    padding: EdgeInsets.all(16),
                    child: GpText(text: 'Span 4/12'),
                  ),
                ),
              ),
              GpCol(
                span: 4,
                child: Card(
                  child: Padding(
                    padding: EdgeInsets.all(16),
                    child: GpText(text: 'Span 4/12'),
                  ),
                ),
              ),
            ],
          ),
          const SizedBox(height: 16),
          GpListTile(
            title: 'ListTile GP',
            subtitle: 'Ideal para settings o listados',
            trailing: const Icon(Icons.arrow_forward_ios, size: 16),
            onTap: () {},
            backgroundColor: theme.colorScheme.surface,
          ),
          const SizedBox(height: 24),
          GpButton(
            text: _loading ? 'Enviando...' : 'Simular petición',
            loading: _loading,
            onPressed: _loading ? null : _simulateRequest,
          ),
          const SizedBox(height: 24),
          Card(
            child: Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  GpText(text: 'Ejemplo: PIN input dinámico'),
                  const SizedBox(height: 12),
                  GpPinInput(
                    key: _pinKey,
                    length: 4,
                    obscure: false,
                    validator: (pin) => pin == '1234' ? null : 'PIN incorrecto',
                    onCompleted: (pin) async {
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(
                          content: Text('PIN verificado correctamente'),
                        ),
                      );
                    },
                  ),
                  const SizedBox(height: 12),
                  Row(
                    children: [
                      GpButton(
                        text: 'Forzar fallo',
                        onPressed: () {
                          (_pinKey.currentState as dynamic)?.reportFailure();
                        },
                      ),
                      const SizedBox(width: 8),
                      GpButton(
                        text: 'Limpiar',
                        onPressed: () {
                          (_pinKey.currentState as dynamic)?.clear();
                        },
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
          const SizedBox(height: 24),
          GpResponsiveTable.simple(
            title: 'Usuarios (paginado)',
            headers: ['ID', 'Nombre', 'Correo', 'Estado'],
            headerTypes: [
              GpTableHeaderType.numeric,
              GpTableHeaderType.text,
              GpTableHeaderType.text,
              GpTableHeaderType.status,
            ],
            borderRadius: 8,
            data: _currentPageRows()
                .map(
                  (row) => [
                    row[0],
                    row[1],
                    row[2],
                    _statusBadge(row[3] as String),
                  ],
                )
                .toList(),
            enablePagination: true,
            pageSize: _pageSize,
            totalItems: _userRows.length,
            currentPage: _tablePage,
            onPageChange: (page) => setState(() => _tablePage = page),
            nextPageText: 'Siguiente',
            previousPageText: 'Anterior',
            pageText: 'Pagina',
            ofText: 'de',
            recordsText: 'registros',
          ),
          if (_responseMessage != null) ...[
            const SizedBox(height: 12),
            GpText(text: _responseMessage!),
          ],
        ],
      ),
    );
  }
}
0
likes
115
points
33
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Colección de componentes, temas, tokens visuales y utilidades responsivas para construir apps Flutter consistentes con el sistema de diseño GP.

Repository (GitHub)
View/report issues

Topics

#design-system #ui-widgets #responsive

License

unknown (license)

Dependencies

cached_network_image, collection, country_picker, dio, flutter, flutter_svg

More

Packages that depend on gp_design