Initial commit: DLS - Dental Lab System

- Flutter + PocketBase dental lab management system
- Clinic & lab dashboards, job tracking, patient management
- Product catalog, finance tracking, multi-language support
- AI assistant integration, realtime notifications
- Windows installer (Inno Setup) included
- Developed by kovakyazilim.com
This commit is contained in:
Emre Emir
2026-06-11 15:57:31 +03:00
commit 8bbc9dbff2
226 changed files with 31308 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
import 'package:flutter/material.dart';
import '../theme/app_theme.dart';
class PillTabs extends StatelessWidget {
const PillTabs({
super.key,
required this.tabs,
required this.selected,
required this.onSelect,
this.counts,
});
final List<String> tabs;
final int selected;
final ValueChanged<int> onSelect;
final List<int?>? counts;
@override
Widget build(BuildContext context) {
return Container(
color: AppColors.surface,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.fromLTRB(16, 10, 16, 10),
child: Row(
children: [
for (int i = 0; i < tabs.length; i++) ...[
if (i > 0) const SizedBox(width: 8),
_PillTab(
label: tabs[i],
count: counts != null && i < counts!.length ? counts![i] : null,
selected: selected == i,
onTap: () => onSelect(i),
),
],
],
),
),
const Divider(height: 1, thickness: 1, color: AppColors.border),
],
),
);
}
}
class _PillTab extends StatelessWidget {
const _PillTab({
required this.label,
required this.selected,
required this.onTap,
this.count,
});
final String label;
final bool selected;
final VoidCallback onTap;
final int? count;
@override
Widget build(BuildContext context) {
return Semantics(
label: label,
button: true,
excludeSemantics: true,
child: GestureDetector(
onTap: onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
decoration: BoxDecoration(
color: selected ? AppColors.primary : Colors.transparent,
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: selected ? AppColors.primary : AppColors.border,
width: 1.5,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
label,
style: TextStyle(
color: selected ? Colors.white : AppColors.textSecondary,
fontSize: 13,
fontWeight: FontWeight.w600,
),
),
if (count != null) ...[
const SizedBox(width: 6),
AnimatedContainer(
duration: const Duration(milliseconds: 200),
padding:
const EdgeInsets.symmetric(horizontal: 6, vertical: 1),
decoration: BoxDecoration(
color: selected
? Colors.white.withValues(alpha: 0.25)
: AppColors.inProgressBg,
borderRadius: BorderRadius.circular(10),
),
child: Text(
'$count',
style: TextStyle(
color: selected ? Colors.white : AppColors.inProgress,
fontSize: 11,
fontWeight: FontWeight.w700,
),
),
),
],
],
),
),
),
);
}
}