Initial commit: Flutter app + PHP/MySQL backend on Hostinger
Replaces Firebase with a self-hosted PHP/MySQL API served from winded.prymsolutions.com. Includes full backend (schema, auth, events, teams, brackets, suggestions, stats, media, file upload) and updated Flutter repositories and domain models. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
enum SuggestionStatus { pending, reviewed, implemented }
|
||||
|
||||
class Suggestion {
|
||||
const Suggestion({
|
||||
required this.id,
|
||||
required this.text,
|
||||
required this.isAnonymous,
|
||||
required this.submittedAt,
|
||||
required this.status,
|
||||
this.userId,
|
||||
this.displayName,
|
||||
});
|
||||
|
||||
final String id;
|
||||
final String text;
|
||||
final bool isAnonymous;
|
||||
final String? userId;
|
||||
final String? displayName;
|
||||
final DateTime submittedAt;
|
||||
final SuggestionStatus status;
|
||||
|
||||
Suggestion copyWith({
|
||||
String? id,
|
||||
String? text,
|
||||
bool? isAnonymous,
|
||||
String? userId,
|
||||
String? displayName,
|
||||
DateTime? submittedAt,
|
||||
SuggestionStatus? status,
|
||||
}) {
|
||||
return Suggestion(
|
||||
id: id ?? this.id,
|
||||
text: text ?? this.text,
|
||||
isAnonymous: isAnonymous ?? this.isAnonymous,
|
||||
userId: userId ?? this.userId,
|
||||
displayName: displayName ?? this.displayName,
|
||||
submittedAt: submittedAt ?? this.submittedAt,
|
||||
status: status ?? this.status,
|
||||
);
|
||||
}
|
||||
|
||||
factory Suggestion.fromJson(Map<String, dynamic> data) {
|
||||
return Suggestion(
|
||||
id: (data['id'] as String?) ?? '',
|
||||
text: (data['text'] as String?) ?? '',
|
||||
isAnonymous: _parseBool(data['is_anonymous']),
|
||||
userId: data['user_id'] as String?,
|
||||
displayName: data['display_name'] as String?,
|
||||
submittedAt: _parseDate(data['submitted_at']) ?? DateTime.now(),
|
||||
status: _parseStatus(data['status'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, Object?> toJson() {
|
||||
return <String, Object?>{
|
||||
'text': text,
|
||||
'is_anonymous': isAnonymous,
|
||||
'user_id': isAnonymous ? null : userId,
|
||||
'display_name': isAnonymous ? null : displayName,
|
||||
'status': status.name,
|
||||
};
|
||||
}
|
||||
|
||||
static DateTime? _parseDate(Object? v) {
|
||||
if (v is String && v.isNotEmpty) return DateTime.tryParse(v);
|
||||
return null;
|
||||
}
|
||||
|
||||
static bool _parseBool(Object? v) {
|
||||
if (v is bool) return v;
|
||||
if (v is int) return v != 0;
|
||||
if (v is String) return v == '1' || v.toLowerCase() == 'true';
|
||||
return false;
|
||||
}
|
||||
|
||||
static SuggestionStatus _parseStatus(String? raw) {
|
||||
switch (raw) {
|
||||
case 'reviewed':
|
||||
return SuggestionStatus.reviewed;
|
||||
case 'implemented':
|
||||
return SuggestionStatus.implemented;
|
||||
default:
|
||||
return SuggestionStatus.pending;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
return other is Suggestion &&
|
||||
other.id == id &&
|
||||
other.text == text &&
|
||||
other.isAnonymous == isAnonymous &&
|
||||
other.userId == userId &&
|
||||
other.displayName == displayName &&
|
||||
other.submittedAt == submittedAt &&
|
||||
other.status == status;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
id, text, isAnonymous, userId, displayName, submittedAt, status,
|
||||
);
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'Suggestion(id: $id, status: ${status.name}, anonymous: $isAnonymous)';
|
||||
}
|
||||
Reference in New Issue
Block a user