Files
please-pay-me/mobile/lib/features/legal/legal_consent.dart
T
2026-09-21 04:06:43 +03:00

144 lines
4.6 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:please_pay_me/core/legal/legal_links.dart';
import 'package:please_pay_me/theme/theme.dart';
import 'package:please_pay_me/ui/ui.dart';
class LegalAcceptance {
const LegalAcceptance({this.offer = false, this.consent = false});
final bool offer;
final bool consent;
bool get accepted => offer && consent;
LegalAcceptance copyWith({bool? offer, bool? consent}) {
return LegalAcceptance(offer: offer ?? this.offer, consent: consent ?? this.consent);
}
}
class LegalConsentBlock extends StatelessWidget {
const LegalConsentBlock({
super.key,
required this.value,
required this.onChanged,
required this.cabinetUrl,
});
final LegalAcceptance value;
final ValueChanged<LegalAcceptance> onChanged;
final String cabinetUrl;
@override
Widget build(BuildContext context) {
return Column(
children: [
_LegalCheckRow(
checkboxKey: const Key('legal-offer-check'),
value: value.offer,
onChanged: (next) => onChanged(value.copyWith(offer: next)),
child: Text.rich(
TextSpan(
style: TextStyle(
fontSize: 13,
height: 1.35,
color: AppColors.of(context, AppColors.secondaryLabel),
),
children: [
const TextSpan(text: 'Я принимаю условия '),
_LinkSpan(
text: 'Пользовательского соглашения',
color: AppColors.of(context, AppColors.accent),
onTap: () => openLegalDocument(context, LegalLinks.resolve(cabinetUrl, LegalLinks.offer)),
),
const TextSpan(text: ' (публичной оферты).'),
],
),
),
),
const SizedBox(height: AppSpacing.s3),
_LegalCheckRow(
checkboxKey: const Key('legal-consent-check'),
value: value.consent,
onChanged: (next) => onChanged(value.copyWith(consent: next)),
child: Text.rich(
TextSpan(
style: TextStyle(
fontSize: 13,
height: 1.35,
color: AppColors.of(context, AppColors.secondaryLabel),
),
children: [
const TextSpan(
text:
'Я даю согласие на обработку моих персональных данных (email, аватар, данные о транзакциях), полученных от сервиса Яндекс и введённых мной, в целях предоставления доступа к Сервису. Согласие действует до его отзыва. ',
),
_LinkSpan(
text: 'Текст согласия',
color: AppColors.of(context, AppColors.accent),
onTap: () =>
openLegalDocument(context, LegalLinks.resolve(cabinetUrl, LegalLinks.consent)),
),
],
),
),
),
],
);
}
}
class _LinkSpan extends WidgetSpan {
_LinkSpan({required String text, required Color color, required VoidCallback onTap})
: super(
alignment: PlaceholderAlignment.baseline,
baseline: TextBaseline.alphabetic,
child: GestureDetector(
onTap: onTap,
child: Text(
text,
style: TextStyle(
fontSize: 13,
height: 1.35,
color: color,
decoration: TextDecoration.underline,
),
),
),
);
}
class _LegalCheckRow extends StatelessWidget {
const _LegalCheckRow({
this.checkboxKey,
required this.value,
required this.onChanged,
required this.child,
});
final Key? checkboxKey;
final bool value;
final ValueChanged<bool> onChanged;
final Widget child;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => onChanged(!value),
behavior: HitTestBehavior.opaque,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
key: checkboxKey,
value ? CupertinoIcons.checkmark_square_fill : CupertinoIcons.square,
size: 22,
color: AppColors.of(context, value ? AppColors.accent : AppColors.systemGray),
),
const SizedBox(width: AppSpacing.s2),
Expanded(child: child),
],
),
);
}
}