import 'dart:io'; import 'dart:ui'; import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '../../core/theme.dart'; import '../../widgets/atoms/custom_button.dart'; import '../../widgets/atoms/scanner_overlay.dart'; class CameraCaptureScreen extends StatefulWidget { const CameraCaptureScreen({Key? key}) : super(key: key); @override State createState() => _CameraCaptureScreenState(); } class _CameraCaptureScreenState extends State { CameraController? _controller; Future? _initializeControllerFuture; XFile? _capturedImage; bool _isCameraInitialized = false; @override void initState() { super.initState(); _initializeCamera(); } Future _initializeCamera() async { final cameras = await availableCameras(); final firstCamera = cameras.firstWhere( (camera) => camera.lensDirection == CameraLensDirection.front, orElse: () => cameras.first, ); _controller = CameraController( firstCamera, ResolutionPreset.medium, enableAudio: false, ); _initializeControllerFuture = _controller!.initialize(); await _initializeControllerFuture; if (mounted) { setState(() { _isCameraInitialized = true; }); } } @override void dispose() { _controller?.dispose(); super.dispose(); } Future _takePicture() async { try { await _initializeControllerFuture; final image = await _controller!.takePicture(); HapticFeedback.lightImpact(); if (!mounted) return; setState(() { _capturedImage = image; }); } catch (e) { print(e); } } void _retakePicture() { setState(() { _capturedImage = null; }); } void _usePicture() { if (_capturedImage != null) { Navigator.pop(context, File(_capturedImage!.path)); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, leading: IconButton( icon: Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.black.withOpacity(0.5), shape: BoxShape.circle, ), child: const Icon(Icons.close, color: Colors.white, size: 16), ), onPressed: () => Navigator.pop(context), ), ), body: Stack( children: [ if (_isCameraInitialized) SizedBox.expand( child: FittedBox( fit: BoxFit.cover, child: SizedBox( width: _controller!.value.previewSize?.height ?? MediaQuery.of(context).size.width, height: _controller!.value.previewSize?.width ?? MediaQuery.of(context).size.height, child: CameraPreview(_controller!), ), ), ) else const Center(child: CircularProgressIndicator(color: Colors.white)), if (_capturedImage != null) SizedBox.expand( child: Image.file( File(_capturedImage!.path), fit: BoxFit.cover, ), ), ScannerOverlay( borderColor: _capturedImage != null ? AppTheme.statusGreen : AppTheme.primaryBlue, isScanning: _capturedImage == null, ), Positioned( top: MediaQuery.of(context).padding.top + kToolbarHeight + 20, left: 20, right: 20, child: Column( children: [ Text( "Ambil Foto Selfie", style: AppTheme.heading3.copyWith(color: Colors.white), ), const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular(20), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10), decoration: BoxDecoration( color: Colors.white.withOpacity(0.15), borderRadius: BorderRadius.circular(20), border: Border.all(color: Colors.white.withOpacity(0.3)), ), child: Text( _capturedImage != null ? "Foto berhasil diambil ✓" : "Posisikan wajah di dalam bingkai", textAlign: TextAlign.center, style: AppTheme.bodyLarge.copyWith( color: _capturedImage != null ? AppTheme.statusGreen : Colors.white, fontWeight: FontWeight.bold, ), ), ), ), ), ], ), ), Positioned( bottom: 40, left: 20, right: 20, child: _capturedImage != null ? Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( child: CustomButton( text: "Foto Ulang", type: ButtonType.secondary, onPressed: _retakePicture, icon: Icons.refresh, ), ), const SizedBox(width: 16), Expanded( child: CustomButton( text: "Gunakan", type: ButtonType.primary, onPressed: _usePicture, icon: Icons.check, backgroundColor: AppTheme.statusGreen, ), ), ], ) : Center( child: GestureDetector( onTap: _takePicture, child: Container( width: 76, height: 76, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all(color: Colors.white.withOpacity(0.8), width: 6), color: Colors.white.withOpacity(0.2), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 10, ) ] ), child: Container( margin: const EdgeInsets.all(6), decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white, ), ), ), ), ), ), ], ), ); } }