import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '../../app/theme.dart'; import '../../core/env.dart'; import '../../data/catalog_repository.dart'; import '../profile/profile_screen.dart'; enum _Kind { claim('claim', 'This is my song', 'Credit me (or my family member) as the singer, writer or composer.'), takedown('takedown', 'Please remove this song', 'I am the artist, a family member or the rights holder.'), wrongInfo('wrong_info', 'The details are wrong', 'Title, singer, album or occasion needs correcting.'), other('other', 'Something else', 'Sound problem, offensive content or anything else.'); const _Kind(this.id, this.title, this.subtitle); final String id; final String title; final String subtitle; } /// "Is this your song?" / report a problem. Goes to the admin team's queue. class ReportScreen extends ConsumerStatefulWidget { const ReportScreen({super.key, this.trackId}); final String? trackId; @override ConsumerState createState() => _ReportScreenState(); } class _ReportScreenState extends ConsumerState { _Kind _kind = _Kind.claim; final _name = TextEditingController(); final _contact = TextEditingController(); final _song = TextEditingController(); final _message = TextEditingController(); bool _sending = false; bool _sent = false; @override void initState() { super.initState(); if (!Env.hasSupabase) return; _contact.text = Supabase.instance.client.auth.currentUser?.email ?? ''; ref.read(profileProvider.future).then((p) { if (mounted && p?.name != null && _name.text.isEmpty) setState(() => _name.text = p!.name!); }).ignore(); } @override void dispose() { for (final c in [_name, _contact, _song, _message]) { c.dispose(); } super.dispose(); } bool get _valid => _name.text.trim().isNotEmpty && _contact.text.trim().length >= 6 && _message.text.trim().length >= 5 && (widget.trackId != null || _song.text.trim().isNotEmpty); Future _send() async { setState(() => _sending = true); try { await Supabase.instance.client.from('takedown_requests').insert({ 'track_id': widget.trackId, 'kind': _kind.id, 'requester': _name.text.trim(), 'contact': _contact.text.trim(), 'reason': widget.trackId == null ? 'Song: ${_song.text.trim()}\n\n${_message.text.trim()}' : _message.text.trim(), }); setState(() => _sent = true); } catch (_) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Could not send. Check your connection, or email support@nkbmusic.com.')), ); } } finally { if (mounted) setState(() => _sending = false); } } @override Widget build(BuildContext context) { final text = Theme.of(context).textTheme; final catalog = ref.watch(catalogProvider).value; final track = widget.trackId == null ? null : catalog?.trackById(widget.trackId!); if (_sent) { return Scaffold( appBar: AppBar(), body: Padding( padding: const EdgeInsets.all(24), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const Icon(Icons.favorite_rounded, color: NkColors.sun, size: 56), const SizedBox(height: 16), Text('Thank you', textAlign: TextAlign.center, style: text.headlineMedium), const SizedBox(height: 8), const Text( 'We have received your message and will get back to you, usually within 7 days. ' 'Genuine removal requests are acted on as soon as we have checked them.', textAlign: TextAlign.center, style: TextStyle(color: NkColors.muted, height: 1.5), ), const SizedBox(height: 24), FilledButton(onPressed: () => context.pop(), child: const Text('Done')), ], ), ), ); } return Scaffold( appBar: AppBar(title: const Text('Is this your song?')), body: ListView( padding: const EdgeInsets.fromLTRB(20, 0, 20, 32), children: [ if (track != null) Text('About "${track.titleLatin}"', style: text.titleMedium?.copyWith(color: NkColors.sun)), const SizedBox(height: 8), const Text( 'We want every artist credited properly. Tell us what is going on and our team will review it.', style: TextStyle(color: NkColors.muted, height: 1.5), ), const SizedBox(height: 12), RadioGroup<_Kind>( groupValue: _kind, onChanged: (k) => setState(() => _kind = k ?? _kind), child: Column( children: [ for (final k in _Kind.values) RadioListTile<_Kind>( value: k, contentPadding: EdgeInsets.zero, title: Text(k.title, style: const TextStyle(fontWeight: FontWeight.w700)), subtitle: Text(k.subtitle, style: const TextStyle(color: NkColors.muted)), ), ], ), ), const SizedBox(height: 8), if (track == null) ...[ TextField( controller: _song, onChanged: (_) => setState(() {}), decoration: const InputDecoration(labelText: 'Which song?', hintText: 'Song title and album'), ), const SizedBox(height: 12), ], TextField( controller: _name, textCapitalization: TextCapitalization.words, onChanged: (_) => setState(() {}), decoration: const InputDecoration(labelText: 'Your name'), ), const SizedBox(height: 12), TextField( controller: _contact, onChanged: (_) => setState(() {}), decoration: const InputDecoration( labelText: 'Email or WhatsApp number', helperText: 'Only our team sees this, to reply to you.', ), ), const SizedBox(height: 12), TextField( controller: _message, minLines: 4, maxLines: 8, onChanged: (_) => setState(() {}), decoration: const InputDecoration( labelText: 'Tell us more', hintText: 'For example: who sang it, who wrote it, the correct title, or why it should be removed.', alignLabelWithHint: true, ), ), const SizedBox(height: 20), FilledButton( onPressed: _valid && !_sending && Env.hasSupabase ? _send : null, child: _sending ? const SizedBox.square(dimension: 22, child: CircularProgressIndicator(strokeWidth: 2.5)) : const Text('Send to the Nanga Kathai team'), ), ], ), ); } }