flutterx_starter_kit 0.0.6 copy "flutterx_starter_kit: ^0.0.6" to clipboard
flutterx_starter_kit: ^0.0.6 copied to clipboard

A comprehensive starter kit that accelerates Flutter app development with ready-to-use components and best practices, especially for GetX state management.

example/example.md

Example #

import 'dart:developer';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutterx_starter_kit/flutterx_starter_kit.dart';

void main() async {
  // Start code
  WidgetsFlutterBinding.ensureInitialized();

  await dotenv.load(fileName: '.env');
  final base = dotenv.env['API_BASE_URL'];
  ApiClient.init(ApiConfig(baseUrl: base!));

  // Configure TextKit font
  TextKitConfig.setFont('fredoka');
  // End code

  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'eQuran Demo',
      theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.green),
      home: const SuratDetailPage(nomorSurat: 1),
    );
  }
}

class SuratDetailPage extends StatefulWidget {
  const SuratDetailPage({super.key, required this.nomorSurat});
  final int nomorSurat;

  @override
  State<SuratDetailPage> createState() => _SuratDetailPageState();
}

class _SuratDetailPageState extends State<SuratDetailPage> {
  late Future<Map<String, dynamic>> _futureDetail;

  @override
  void initState() {
    super.initState();
    _futureDetail = _fetchDetail();
  }

  Future<Map<String, dynamic>> _fetchDetail() async {
    final res = await ApiClient.instance.get('/surat/1');
    if (res.statusCode != 200) {
      throw ApiException(
        'Unexpected status ${res.statusCode}',
        statusCode: res.statusCode,
        data: res.data,
      );
    }

    final root = (res.data is Map) ? (res.data as Map) : <String, dynamic>{};
    final data = root['data'];
    if (data is Map) {
      return data.map((k, v) => MapEntry(k.toString(), v));
    }
    return <String, dynamic>{};
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Detail Surat')),
      body: FutureBuilder<Map<String, dynamic>>(
        future: _futureDetail,
        builder: (context, snap) {
          if (snap.connectionState != ConnectionState.done) {
            return const Center(child: CircularProgressIndicator());
          }
          if (snap.hasError) {
            final hint = kIsWeb
                ? '\n\nHint Web: Jika error CORS, coba emulator Android/iOS, '
                      'atau gunakan proxy CORS untuk development.'
                : '';
            log('Error: ${snap.error}');
            return SingleChildScrollView(
              padding: const EdgeInsets.all(16),
              child: Text('Error: ${snap.error}$hint'),
            );
          }

          final detail = snap.data ?? const <String, dynamic>{};
          if (detail.isEmpty) {
            return const Center(child: Text('Tidak ada data.'));
          }

          final nomor = detail['nomor']?.toString() ?? '-';
          final nama = detail['nama']?.toString() ?? '';
          final namaLatin = detail['namaLatin']?.toString() ?? '';
          final arti = detail['arti']?.toString() ?? '';
          final tempatTurun = detail['tempatTurun']?.toString() ?? '';
          final jumlahAyat = detail['jumlahAyat']?.toString() ?? '-';
          final deskripsi = detail['deskripsi']?.toString() ?? '';

          final ayatListDynamic = detail['ayat'];
          final List<Map<String, dynamic>> ayatList = (ayatListDynamic is List)
              ? ayatListDynamic
                    .whereType<Map>()
                    .map((e) => e.map((k, v) => MapEntry(k.toString(), v)))
                    .cast<Map<String, dynamic>>()
                    .toList()
              : const [];

          return ListView(
            children: [
              ListTile(
                title: Text('$namaLatin  (No. $nomor)'),
                subtitle: Text(
                  [
                    if (nama.isNotEmpty) 'Arab: $nama',
                    if (arti.isNotEmpty) 'Arti: $arti',
                    if (tempatTurun.isNotEmpty) 'Turun: $tempatTurun',
                    'Jumlah ayat: $jumlahAyat',
                  ].join(' • '),
                ),
              ),
              if (deskripsi.isNotEmpty)
                Padding(
                  padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
                  child: Text(deskripsi),
                ),
              const Divider(),
              Padding(
                padding: EdgeInsets.all(16),
                // TextKit usage
                child: TextKit.bodyLarge(
                  'Daftar Ayat',
                  color: Colors.blueAccent,
                ),
              ),
              if (ayatList.isEmpty)
                const Padding(
                  padding: EdgeInsets.all(16),
                  child: Text('Belum ada daftar ayat.'),
                )
              else
                ...ayatList.map((a) {
                  final no = a['nomorAyat']?.toString() ?? '';
                  final arab = a['teksArab']?.toString() ?? '';
                  final latin = a['teksLatin']?.toString() ?? '';
                  final indo = a['teksIndonesia']?.toString() ?? '';
                  return ListTile(
                    leading: CircleAvatar(child: Text(no)),
                    title: Text(arab, textAlign: TextAlign.right),
                    subtitle: Text('$latin\n$indo'),
                    isThreeLine: true,
                  );
                }),
              const SizedBox(height: 24),
            ],
          );
        },
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:flutterx_starter_kit/flutterx_starter_kit.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: SizedBox(
            width: double.infinity,
            child: Column(
              spacing: 8,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    TextKit.displayLarge('Display Large'),
                    TextKit.displayMedium('Display Medium'),
                    TextKit.displaySmall('Display Small'),
                  ],
                ),
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    TextKit.headlineLarge('Headline Large'),
                    TextKit.headlineMedium('Headline Medium'),
                    TextKit.headlineSmall('Headline Small'),
                  ],
                ),
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    TextKit.titleLarge('Title Large'),
                    TextKit.titleMedium('Title Medium'),
                    TextKit.titleSmall('Title Small'),
                  ],
                ),
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    TextKit.bodyLarge('Body Large'),
                    TextKit.bodyMedium('Body Medium'),
                    TextKit.bodySmall('Body Small'),
                  ],
                ),
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    TextKit.labelLarge('Label Large'),
                    TextKit.labelMedium('Label Medium'),
                    TextKit.labelSmall('Label Small'),
                  ],
                ),
                SizedBox(height: 40),
                TextKit.headlineMedium('Other examples'),
                Row(
                  spacing: 8,
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    ElevatedButton(
                      onPressed: () {},
                      child: TextKit.labelLarge('Button Text'),
                    ),
                    Chip(
                      label: TextKit.labelMedium(
                        'Chip Label',
                        color: Colors.black,
                      ),
                    ),
                    TextKit.bodyLarge(
                      'Very long text that might overflow...',
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                      color: Colors.blue,
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:flutterx_starter_kit/flutterx_starter_kit.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: SizedBox(
            width: double.infinity,
            child: Column(
              spacing: 8,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ButtonKit(
                  text: "Sign In",
                  textColor: Colors.white,
                  bgColor: Colors.blue,
                  press: () {
                    SnackbarKit.success(
                      context,
                      'Profile updated!',
                      position: SnackbarPosition.bottom,
                    );
                    SnackbarKit.error(
                      context,
                      'Connection failed',
                      position: SnackbarPosition.bottom,
                    );
                    SnackbarKit.warning(
                      context,
                      'Low storage',
                      position: SnackbarPosition.bottom,
                    );
                    SnackbarKit.info(
                      context,
                      'New update available',
                      position: SnackbarPosition.bottom,
                    );
                    SnackbarKit.normal(
                      context,
                      'Settings saved',
                      position: SnackbarPosition.bottom,
                    );
                  },
                  height: 50,
                ),
                ButtonKitGradient(
                  text: "This is Gradient",
                  textColor: Colors.white,
                  bgColor1: Colors.cyan,
                  bgColor2: Colors.purpleAccent,
                  press: () {},
                  width: 200,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

1
likes
160
points
12
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive starter kit that accelerates Flutter app development with ready-to-use components and best practices, especially for GetX state management.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

args, flutter, flutter_dotenv, google_fonts, http, path, recase

More

Packages that depend on flutterx_starter_kit