feat(feedback): implement user feedback collection system with email reporting
Backend: - Add user_feedback table with RLS policy - Create feedback submission API (multipart/form-data) - Implement xlsx report generation with embedded images - Add scheduled email delivery via Feishu SMTP - Create HTML email templates (daily_report, no_feedback) Frontend: - Add feedback screen with type selection and image picker - Support anonymous submission via skipAuth flag - Collect device info and app version Protocol: - Document feedback API contract and error codes - Update http-error-codes.md with FEEDBACK_* codes
This commit is contained in:
@@ -73,16 +73,16 @@ class HomeScreen extends StatefulWidget {
|
||||
class _HomeScreenState extends State<HomeScreen> {
|
||||
MainTab _currentTab = MainTab.home;
|
||||
late final InviteRepository _inviteRepository;
|
||||
late final ApiClient _apiClient;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final inviteApi = InviteApi(
|
||||
apiClient: ApiClient(
|
||||
baseUrl: appDependencies.backendUrl,
|
||||
tokenProvider: widget.sessionStore.getToken,
|
||||
),
|
||||
_apiClient = ApiClient(
|
||||
baseUrl: appDependencies.backendUrl,
|
||||
tokenProvider: widget.sessionStore.getToken,
|
||||
);
|
||||
final inviteApi = InviteApi(apiClient: _apiClient);
|
||||
_inviteRepository = InviteRepositoryImpl(inviteApi: inviteApi);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_tryShowWelcomeDialog();
|
||||
@@ -135,6 +135,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
||||
settings: widget.profileSettings,
|
||||
coinBalance: widget.coinBalance,
|
||||
inviteRepository: _inviteRepository,
|
||||
apiClient: _apiClient,
|
||||
onLocaleChanged: widget.onLocaleChanged,
|
||||
onSettingsChanged: widget.onProfileSettingsChanged,
|
||||
onSaveProfile: widget.onSaveProfile,
|
||||
@@ -563,6 +564,7 @@ class _ProfileTab extends StatelessWidget {
|
||||
required this.settings,
|
||||
required this.coinBalance,
|
||||
required this.inviteRepository,
|
||||
required this.apiClient,
|
||||
required this.onLocaleChanged,
|
||||
required this.onSettingsChanged,
|
||||
required this.onSaveProfile,
|
||||
@@ -575,6 +577,7 @@ class _ProfileTab extends StatelessWidget {
|
||||
final ProfileSettingsV1 settings;
|
||||
final int coinBalance;
|
||||
final InviteRepository inviteRepository;
|
||||
final ApiClient apiClient;
|
||||
final Future<void> Function(String languageTag) onLocaleChanged;
|
||||
final Future<void> Function(ProfileSettingsV1 settings) onSettingsChanged;
|
||||
final Future<ProfileSettingsV1> Function(ProfileSettingsV1 updated)
|
||||
@@ -590,6 +593,7 @@ class _ProfileTab extends StatelessWidget {
|
||||
settings: settings,
|
||||
coinBalance: coinBalance,
|
||||
inviteRepository: inviteRepository,
|
||||
apiClient: apiClient,
|
||||
onInterfaceLanguageChanged: onLocaleChanged,
|
||||
onSettingsChanged: onSettingsChanged,
|
||||
onSaveProfile: onSaveProfile,
|
||||
|
||||
Reference in New Issue
Block a user