Add buddy-to-dive center conversion feature#712
Conversation
Implemented functionality to convert a buddy into a dive center, including database updates, localization changes, and UI handling. **Key changes:** - Added `convertBuddyToDiveCenter` method in `BuddyConversionRepository` to create dive centers, update linked dives, and clean up buddy records. - Updated UI to include "Convert to Dive Center" action in buddy detail options. - Added confirmation and success messages to localization files across supported languages. - Enhanced providers to integrate conversion logic and UI response. This update enables users to manage buddies and dive centers more flexibly and ensures proper handling of related data integrity.
There was a problem hiding this comment.
Pull request overview
Adds a “buddy → dive center” conversion flow to address mis-imported Subsurface dive center tags, wiring together DB migration logic, Riverpod provider refresh, UI entry points, and localized messaging.
Changes:
- Introduces
BuddyConversionRepository.convertBuddyToDiveCenterto create a dive center, relink dives, and delete the buddy. - Adds a “Convert to Dive Center” action + confirmation dialog to the buddy detail UI, then navigates to the new dive center.
- Extends localization keys/messages and adds a repository test for the conversion behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/features/buddies/data/repositories/buddy_conversion_repository_test.dart | Adds a repository-level test for converting a buddy and updating linked dives. |
| lib/features/buddies/data/repositories/buddy_conversion_repository.dart | Implements the buddy→dive center conversion transaction and sync bookkeeping. |
| lib/features/buddies/data/repositories/buddy_repository.dart | Exposes conversion via BuddyRepository.convertToDiveCenter delegating to the new repository. |
| lib/features/buddies/presentation/providers/buddy_providers.dart | Adds notifier method to run conversion and invalidate relevant providers. |
| lib/features/buddies/presentation/pages/buddy_detail_page.dart | Adds menu action, confirmation dialog, snackbar, and navigation after conversion. |
| lib/l10n/arb/app_en.arb | Adds new English localization keys for the conversion flow. |
| lib/l10n/arb/app_localizations.dart | Updates the generated localization interface with new conversion getters/messages. |
| lib/l10n/arb/app_localizations_en.dart | Adds generated English implementations for the new conversion strings. |
| lib/l10n/arb/app_localizations_de.dart | Adds generated German-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_es.dart | Adds generated Spanish-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_fr.dart | Adds generated French-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_it.dart | Adds generated Italian-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_nl.dart | Adds generated Dutch-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_pt.dart | Adds generated Portuguese-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_zh.dart | Adds generated Chinese-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_ar.dart | Adds generated Arabic-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_he.dart | Adds generated Hebrew-locale implementations (currently falling back to English). |
| lib/l10n/arb/app_localizations_hu.dart | Adds generated Hungarian-locale implementations (currently falling back to English). |
| // 5. Delete the buddy | ||
| await (_db.delete( | ||
| _db.buddies, | ||
| )..where((t) => t.id.equals(buddy.id))).go(); | ||
| await _syncRepository.logDeletion( | ||
| entityType: 'buddies', | ||
| recordId: buddy.id, | ||
| ); |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
|
📦 Build artifacts for this PR · commit
Artifacts expire in 7 days. Downloading requires being signed in to GitHub. The macOS build is ad-hoc signed — right-click → Open on first launch. Updated automatically on each push. |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 10 comments.
Comments suppressed due to low confidence (1)
lib/features/buddies/data/repositories/buddy_conversion_repository.dart:111
- Buddy deletion relies on FK cascades for other buddy-owned tables (e.g. certifications.buddyId and buddy_roles.buddyId are defined with onDelete: cascade), but this conversion flow only tombstones dive_buddies + buddies. Cascaded deletes won’t write deletion_log entries, so buddy certifications/roles can resurrect on the next sync. Mirror BuddyRepository.deleteBuddy’s pattern by explicitly deleting + logging tombstones for buddy-owned certifications and buddy_roles inside the same transaction before deleting the buddy.
// 5. Delete the buddy
await (_db.delete(
_db.buddies,
)..where((t) => t.id.equals(buddy.id))).go();
await _syncRepository.logDeletion(
| @override | ||
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
| String buddies_conversion_confirmBody(String name) { | ||
| return 'This will convert $name into a dive center and update all shared dives. This action cannot be undone.'; | ||
| } |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
lib/features/buddies/data/repositories/buddy_conversion_repository.dart:111
- The conversion deletes the buddy directly, but (like BuddyRepository.deleteBuddy) needs to explicitly delete + tombstone any buddy-owned certifications before deleting the buddy. Otherwise the FK cascade removes cert rows without creating deletion-log entries, which can cause those certifications to resurrect on the next sync.
// 5. Delete the buddy
await (_db.delete(
_db.buddies,
)..where((t) => t.id.equals(buddy.id))).go();
await _syncRepository.logDeletion(
lib/l10n/arb/app_en.arb:612
- These new buddies conversion strings were only added to app_en.arb. The other locale ARB files (e.g., app_fr.arb/app_de.arb) don’t contain these keys, which is why the generated app_localizations_.dart files currently fall back to English for these messages. This also contradicts the PR description’s claim that localization was added across supported languages.
"buddies_action_clearSearch": "Clear search",
"buddies_action_convertToDiveCenter": "Convert to Dive Center",
"buddies_action_edit": "Edit buddy",
Feel free to squash this if you feel it is not needed.
Implemented functionality to convert a buddy into a dive center, including database updates, localization changes, and UI handling.
Key changes:
convertBuddyToDiveCentermethod inBuddyConversionRepositoryto create dive centers, update linked dives, and clean up buddy records.This update enables users to manage buddies and dive centers more flexibly and ensures proper handling of related data integrity.
Summary
When importing data from subsurface, I have had a few dive center tags get converted over to a dive buddy instead of a dive shop. This change simply allow the conversion of a buddy into a dive shop.
Changes
New Conversion Repository: Added BuddyConversionRepository with logic to convert a Buddy into a DiveCenter. This process includes:
◦
Creating a new DiveCenter entry with the buddy's details (name, email, phone, notes).
◦
Updating all dives linked to that buddy to reference the new dive center.
◦
Removing the buddy from the database and cleaning up the junction table links.
•
UI Integration: Added a "Convert to Dive Center" option in the BuddyDetailPage options menu, including a confirmation dialog to prevent accidental conversions.
•
State Management: Updated BuddyListNotifier to handle the conversion flow, which includes calling the repository and invalidating relevant providers to refresh the UI.
•
Localization: Added new strings for the conversion action, confirmation title/body, and success notifications across all supported languages (EN, DE, ES, FR, etc.).
•
Automated Testing: Implemented a comprehensive test suite in buddy_conversion_repository_test.dart to verify that data is correctly migrated and buddy records are properly deleted.
•
Navigation & Feedback: Added logic to show a success snackbar upon completion and automatically navigate the user to the newly created dive center's detail page.
Test Plan
flutter testpassesflutter analyzepassesScreenshots