refactor: Replace attire option 'icon' field with 'description' across the schema and data models, and update the UI to display the new description.

This commit is contained in:
Achintha Isuru
2026-02-24 15:13:06 -05:00
parent 7744dbf1b3
commit b29351a3aa
6 changed files with 68 additions and 68 deletions

View File

@@ -4,23 +4,23 @@ import 'package:equatable/equatable.dart';
///
/// Attire items are specific clothing or equipment required for jobs.
class AttireItem extends Equatable {
/// Creates an [AttireItem].
const AttireItem({
required this.id,
required this.label,
this.iconName,
this.description,
this.imageUrl,
this.isMandatory = false,
});
/// Unique identifier of the attire item.
final String id;
/// Display name of the item.
final String label;
/// Name of the icon to display (mapped in UI).
final String? iconName;
/// Optional description for the attire item.
final String? description;
/// URL of the reference image.
final String? imageUrl;
@@ -29,5 +29,11 @@ class AttireItem extends Equatable {
final bool isMandatory;
@override
List<Object?> get props => <Object?>[id, label, iconName, imageUrl, isMandatory];
List<Object?> get props => <Object?>[
id,
label,
description,
imageUrl,
isMandatory,
];
}

View File

@@ -8,26 +8,30 @@ import '../../domain/repositories/attire_repository.dart';
///
/// Delegates data access to [DataConnectService].
class AttireRepositoryImpl implements AttireRepository {
/// Creates an [AttireRepositoryImpl].
AttireRepositoryImpl({DataConnectService? service})
: _service = service ?? DataConnectService.instance;
: _service = service ?? DataConnectService.instance;
/// The Data Connect service.
final DataConnectService _service;
@override
Future<List<AttireItem>> getAttireOptions() async {
return _service.run(() async {
final QueryResult<ListAttireOptionsData, void> result =
await _service.connector.listAttireOptions().execute();
final QueryResult<ListAttireOptionsData, void> result = await _service
.connector
.listAttireOptions()
.execute();
return result.data.attireOptions
.map((ListAttireOptionsAttireOptions e) => AttireItem(
id: e.itemId,
label: e.label,
iconName: e.icon,
imageUrl: e.imageUrl,
isMandatory: e.isMandatory ?? false,
))
.map(
(ListAttireOptionsAttireOptions e) => AttireItem(
id: e.itemId,
label: e.label,
description: e.description,
imageUrl: e.imageUrl,
isMandatory: e.isMandatory ?? false,
),
)
.toList();
});
}

View File

@@ -5,7 +5,6 @@ import 'package:core_localization/core_localization.dart';
import 'package:krow_domain/krow_domain.dart';
class AttireGrid extends StatelessWidget {
const AttireGrid({
super.key,
required this.items,
@@ -53,7 +52,9 @@ class AttireGrid extends StatelessWidget {
) {
return Container(
decoration: BoxDecoration(
color: isSelected ? UiColors.primary.withOpacity(0.1) : Colors.transparent,
color: isSelected
? UiColors.primary.withOpacity(0.1)
: Colors.transparent,
borderRadius: UiConstants.radiusSm,
border: Border.all(
color: isSelected ? UiColors.primary : UiColors.border,
@@ -67,19 +68,17 @@ class AttireGrid extends StatelessWidget {
top: UiConstants.space2,
left: UiConstants.space2,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2,
),
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
decoration: BoxDecoration(
color: UiColors.destructive, // Red
borderRadius: UiConstants.radiusSm,
),
child: Text(
t.staff_profile_attire.status.required,
style: UiTypography.body3m.copyWith( // 12px Medium -> Bold
style: UiTypography.body3m.copyWith(
// 12px Medium -> Bold
fontWeight: FontWeight.bold,
fontSize: 9,
fontSize: 9,
color: UiColors.white,
),
),
@@ -97,11 +96,7 @@ class AttireGrid extends StatelessWidget {
shape: BoxShape.circle,
),
child: const Center(
child: Icon(
UiIcons.check,
color: UiColors.white,
size: 12,
),
child: Icon(UiIcons.check, color: UiColors.white, size: 12),
),
),
),
@@ -119,26 +114,34 @@ class AttireGrid extends StatelessWidget {
height: 80,
width: 80,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
borderRadius: BorderRadius.circular(
UiConstants.radiusBase,
),
image: DecorationImage(
image: NetworkImage(item.imageUrl!),
fit: BoxFit.cover,
),
),
)
: Icon(
_getIcon(item.iconName),
: const Icon(
UiIcons.shirt,
size: 48,
color: UiColors.textPrimary, // Was charcoal
color: UiColors.iconSecondary,
),
const SizedBox(height: UiConstants.space2),
Text(
item.label,
textAlign: TextAlign.center,
style: UiTypography.body2m.copyWith(
color: UiColors.textPrimary,
),
style: UiTypography.body2m.textPrimary,
),
if (item.description != null)
Text(
item.description!,
textAlign: TextAlign.center,
style: UiTypography.body3r.textSecondary,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
@@ -158,7 +161,9 @@ class AttireGrid extends StatelessWidget {
border: Border.all(
color: hasPhoto ? UiColors.primary : UiColors.border,
),
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
borderRadius: BorderRadius.circular(
UiConstants.radiusBase,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -169,7 +174,9 @@ class AttireGrid extends StatelessWidget {
height: 12,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(UiColors.primary),
valueColor: AlwaysStoppedAnimation<Color>(
UiColors.primary,
),
),
)
else if (hasPhoto)
@@ -189,10 +196,12 @@ class AttireGrid extends StatelessWidget {
isUploading
? '...'
: hasPhoto
? t.staff_profile_attire.status.added
: t.staff_profile_attire.status.add_photo,
? t.staff_profile_attire.status.added
: t.staff_profile_attire.status.add_photo,
style: UiTypography.body3m.copyWith(
color: hasPhoto ? UiColors.primary : UiColors.textSecondary,
color: hasPhoto
? UiColors.primary
: UiColors.textSecondary,
),
),
],
@@ -217,23 +226,4 @@ class AttireGrid extends StatelessWidget {
),
);
}
IconData _getIcon(String? name) {
switch (name) {
case 'footprints':
return UiIcons.footprints;
case 'scissors':
return UiIcons.scissors;
case 'user':
return UiIcons.user;
case 'shirt':
return UiIcons.shirt;
case 'hardHat':
return UiIcons.hardHat;
case 'chefHat':
return UiIcons.chefHat;
default:
return UiIcons.help;
}
}
}

View File

@@ -1,7 +1,7 @@
mutation createAttireOption(
$itemId: String!
$label: String!
$icon: String
$description: String
$imageUrl: String
$isMandatory: Boolean
$vendorId: UUID
@@ -10,7 +10,7 @@ mutation createAttireOption(
data: {
itemId: $itemId
label: $label
icon: $icon
description: $description
imageUrl: $imageUrl
isMandatory: $isMandatory
vendorId: $vendorId
@@ -22,7 +22,7 @@ mutation updateAttireOption(
$id: UUID!
$itemId: String
$label: String
$icon: String
$description: String
$imageUrl: String
$isMandatory: Boolean
$vendorId: UUID
@@ -32,7 +32,7 @@ mutation updateAttireOption(
data: {
itemId: $itemId
label: $label
icon: $icon
description: $description
imageUrl: $imageUrl
isMandatory: $isMandatory
vendorId: $vendorId

View File

@@ -3,7 +3,7 @@ query listAttireOptions @auth(level: USER) {
id
itemId
label
icon
description
imageUrl
isMandatory
vendorId
@@ -16,7 +16,7 @@ query getAttireOptionById($id: UUID!) @auth(level: USER) {
id
itemId
label
icon
description
imageUrl
isMandatory
vendorId
@@ -39,7 +39,7 @@ query filterAttireOptions(
id
itemId
label
icon
description
imageUrl
isMandatory
vendorId

View File

@@ -2,7 +2,7 @@ type AttireOption @table(name: "attire_options") {
id: UUID! @default(expr: "uuidV4()")
itemId: String!
label: String!
icon: String
description: String
imageUrl: String
isMandatory: Boolean