Last active
November 15, 2025 03:29
-
-
Save nurrachmat-nr/1685fd14e2b27651991e4d6a3442cf98 to your computer and use it in GitHub Desktop.
PAB1 - Widget
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| class MyScreen extends StatelessWidget { | |
| const MyScreen({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return const Scaffold( | |
| backgroundColor: Colors.white, | |
| body: SafeArea( | |
| child: SingleChildScrollView( | |
| padding: EdgeInsets.all(16), | |
| child: KampusCard(), | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class KampusCard extends StatelessWidget { | |
| const KampusCard({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| final theme = Theme.of(context); | |
| final titleStyle = theme.textTheme.headlineSmall?.copyWith( | |
| fontWeight: FontWeight.w700, | |
| color: Colors.black87, | |
| ); | |
| return Center( | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| // Header image | |
| ClipRRect( | |
| borderRadius: const BorderRadius.vertical(top: Radius.circular(14)), | |
| child: AspectRatio( | |
| aspectRatio: 16 / 9, | |
| child: Image.network( | |
| 'https://mdp.ac.id/mdp2020/wp-content/uploads/2025/02/Kampus-Prestasi-dan-Inovasi-scaled-350x212.jpg', // TODO: ganti sesuai aset Anda | |
| fit: BoxFit.cover, | |
| ), | |
| ), | |
| ), | |
| // Judul & lokasi | |
| Padding( | |
| padding: const EdgeInsets.fromLTRB(16, 16, 16, 4), | |
| child: Text('Universitas Multi Data Palembang', style: titleStyle), | |
| ), | |
| const Padding( | |
| padding: EdgeInsets.fromLTRB(16, 0, 16, 16), | |
| child: Text( | |
| 'Kota Palembang, Prov. Sumatera Selatan', | |
| style: TextStyle(color: Colors.black54, fontSize: 16), | |
| ), | |
| ), | |
| // Info biru | |
| Padding( | |
| padding: const EdgeInsets.symmetric(horizontal: 16), | |
| child: _InfoBlueCard(), | |
| ), | |
| const SizedBox(height: 16), | |
| // Alamat + tombol maps | |
| const _AddressSection(), | |
| const SizedBox(height: 16), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _InfoBlueCard extends StatelessWidget { | |
| const _InfoBlueCard(); | |
| Color get _blue => const Color(0xFF2E77E5); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Container( | |
| decoration: BoxDecoration( | |
| color: _blue, | |
| borderRadius: BorderRadius.circular(14), | |
| ), | |
| padding: const EdgeInsets.all(16), | |
| child: Row( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| // Kolom kiri: Status, Akreditasi, Tanggal | |
| Expanded(child: _LeftMetaColumn()), | |
| const SizedBox(width: 16), | |
| // Kolom kanan: Kontak | |
| Expanded(child: _ContactColumn()), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _LeftMetaColumn extends StatelessWidget { | |
| const _LeftMetaColumn(); | |
| TextStyle get _labelStyle => const TextStyle( | |
| color: Colors.white70, | |
| fontSize: 14, | |
| fontWeight: FontWeight.w600, | |
| ); | |
| TextStyle get _valueStyle => const TextStyle( | |
| color: Colors.white, | |
| fontSize: 18, | |
| fontWeight: FontWeight.w800, | |
| ); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| _SectionLabel('Status', style: _labelStyle), | |
| Text('Aktif', style: _valueStyle), | |
| const SizedBox(height: 16), | |
| _SectionLabel('Akreditasi', style: _labelStyle), | |
| Text('Baik Sekali', style: _valueStyle), | |
| const SizedBox(height: 16), | |
| _SectionLabel('Tanggal Berdiri', style: _labelStyle), | |
| Text('9 April 2021', style: _valueStyle), | |
| ], | |
| ); | |
| } | |
| } | |
| class _ContactColumn extends StatelessWidget { | |
| const _ContactColumn(); | |
| TextStyle get _labelStyle => const TextStyle( | |
| color: Colors.white70, | |
| fontSize: 14, | |
| fontWeight: FontWeight.w600, | |
| ); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| _SectionLabel('Kontak', style: _labelStyle), | |
| const SizedBox(height: 8), | |
| const _IconTextRow(icon: Icons.call_rounded, text: '0711-376400'), | |
| const SizedBox(height: 8), | |
| const _IconTextRow(icon: Icons.mail_rounded, text: '[email protected]'), | |
| const SizedBox(height: 8), | |
| const _IconTextRow( | |
| icon: Icons.public_rounded, | |
| text: 'https://mdp.ac.id', | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _SectionLabel extends StatelessWidget { | |
| final String text; | |
| final TextStyle? style; | |
| const _SectionLabel(this.text, {this.style}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Text(text, style: style); | |
| } | |
| } | |
| class _IconTextRow extends StatelessWidget { | |
| final IconData icon; | |
| final String text; | |
| const _IconTextRow({required this.icon, required this.text}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Row( | |
| children: [ | |
| Container( | |
| width: 34, | |
| height: 34, | |
| decoration: BoxDecoration( | |
| color: Colors.white.withOpacity(0.15), | |
| borderRadius: BorderRadius.circular(10), | |
| ), | |
| child: Icon(icon, color: Colors.white, size: 20), | |
| ), | |
| const SizedBox(width: 10), | |
| Expanded( | |
| child: Text( | |
| text, | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _AddressSection extends StatelessWidget { | |
| const _AddressSection(); | |
| @override | |
| Widget build(BuildContext context) { | |
| final cardColor = Colors.grey.shade100; | |
| return Padding( | |
| padding: const EdgeInsets.symmetric(horizontal: 16), | |
| child: Container( | |
| decoration: BoxDecoration( | |
| color: cardColor, | |
| borderRadius: BorderRadius.circular(14), | |
| ), | |
| padding: const EdgeInsets.all(16), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| const Text( | |
| 'Alamat', | |
| style: TextStyle( | |
| fontWeight: FontWeight.w700, | |
| color: Colors.black87, | |
| ), | |
| ), | |
| const SizedBox(height: 8), | |
| const Text( | |
| 'Jl. Rajawali 14, Kota Palembang,\nProv. Sumatera Selatan', | |
| style: TextStyle(fontSize: 16, color: Colors.black87), | |
| ), | |
| const SizedBox(height: 16), | |
| SizedBox( | |
| width: double.infinity, | |
| child: ElevatedButton( | |
| style: ElevatedButton.styleFrom( | |
| backgroundColor: const Color(0xFF2E77E5), | |
| foregroundColor: Colors.white, | |
| padding: const EdgeInsets.symmetric(vertical: 14), | |
| shape: RoundedRectangleBorder( | |
| borderRadius: BorderRadius.circular(12), | |
| ), | |
| ), | |
| onPressed: () {}, | |
| child: const Text( | |
| 'Lihat Maps', | |
| style: TextStyle(fontWeight: FontWeight.w700, fontSize: 16), | |
| ), | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment