♻️ Make bot management into sheet
This commit is contained in:
		@@ -5,8 +5,11 @@ import 'package:go_router/go_router.dart';
 | 
				
			|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
					import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
				
			||||||
import 'package:island/models/bot.dart';
 | 
					import 'package:island/models/bot.dart';
 | 
				
			||||||
import 'package:island/pods/network.dart';
 | 
					import 'package:island/pods/network.dart';
 | 
				
			||||||
 | 
					import 'package:island/screens/developers/edit_bot.dart';
 | 
				
			||||||
 | 
					import 'package:island/screens/developers/new_bot.dart';
 | 
				
			||||||
import 'package:island/widgets/alert.dart';
 | 
					import 'package:island/widgets/alert.dart';
 | 
				
			||||||
import 'package:island/widgets/content/cloud_files.dart';
 | 
					import 'package:island/widgets/content/cloud_files.dart';
 | 
				
			||||||
 | 
					import 'package:island/widgets/content/sheet.dart';
 | 
				
			||||||
import 'package:island/widgets/response.dart';
 | 
					import 'package:island/widgets/response.dart';
 | 
				
			||||||
import 'package:material_symbols_icons/symbols.dart';
 | 
					import 'package:material_symbols_icons/symbols.dart';
 | 
				
			||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
 | 
					import 'package:riverpod_annotation/riverpod_annotation.dart';
 | 
				
			||||||
@@ -48,12 +51,18 @@ class BotsScreen extends HookConsumerWidget {
 | 
				
			|||||||
                const SizedBox(height: 16),
 | 
					                const SizedBox(height: 16),
 | 
				
			||||||
                ElevatedButton.icon(
 | 
					                ElevatedButton.icon(
 | 
				
			||||||
                  onPressed: () {
 | 
					                  onPressed: () {
 | 
				
			||||||
                    context.pushNamed(
 | 
					                    showModalBottomSheet(
 | 
				
			||||||
                      'developerBotNew',
 | 
					                      context: context,
 | 
				
			||||||
                      pathParameters: {
 | 
					                      isScrollControlled: true,
 | 
				
			||||||
                        'name': publisherName,
 | 
					                      builder:
 | 
				
			||||||
                        'projectId': projectId,
 | 
					                          (context) => SheetScaffold(
 | 
				
			||||||
                      },
 | 
					                            titleText: 'createBot'.tr(),
 | 
				
			||||||
 | 
					                            child: NewBotScreen(
 | 
				
			||||||
 | 
					                              publisherName: publisherName,
 | 
				
			||||||
 | 
					                              projectId: projectId,
 | 
				
			||||||
 | 
					                              isModal: true,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                  },
 | 
					                  },
 | 
				
			||||||
                  icon: const Icon(Symbols.add),
 | 
					                  icon: const Icon(Symbols.add),
 | 
				
			||||||
@@ -74,12 +83,18 @@ class BotsScreen extends HookConsumerWidget {
 | 
				
			|||||||
                  title: Text('bots').tr().padding(horizontal: 8),
 | 
					                  title: Text('bots').tr().padding(horizontal: 8),
 | 
				
			||||||
                  trailing: IconButton(
 | 
					                  trailing: IconButton(
 | 
				
			||||||
                    onPressed: () {
 | 
					                    onPressed: () {
 | 
				
			||||||
                      context.pushNamed(
 | 
					                      showModalBottomSheet(
 | 
				
			||||||
                        'developerBotNew',
 | 
					                        context: context,
 | 
				
			||||||
                        pathParameters: {
 | 
					                        isScrollControlled: true,
 | 
				
			||||||
                          'name': publisherName,
 | 
					                        builder:
 | 
				
			||||||
                          'projectId': projectId,
 | 
					                            (context) => SheetScaffold(
 | 
				
			||||||
                        },
 | 
					                              titleText: 'createBot'.tr(),
 | 
				
			||||||
 | 
					                              child: NewBotScreen(
 | 
				
			||||||
 | 
					                                publisherName: publisherName,
 | 
				
			||||||
 | 
					                                projectId: projectId,
 | 
				
			||||||
 | 
					                                isModal: true,
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
                      );
 | 
					                      );
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                    icon: const Icon(Symbols.add),
 | 
					                    icon: const Icon(Symbols.add),
 | 
				
			||||||
@@ -93,7 +108,6 @@ class BotsScreen extends HookConsumerWidget {
 | 
				
			|||||||
                  itemBuilder: (context, index) {
 | 
					                  itemBuilder: (context, index) {
 | 
				
			||||||
                    final bot = data[index];
 | 
					                    final bot = data[index];
 | 
				
			||||||
                    return Card(
 | 
					                    return Card(
 | 
				
			||||||
                      margin: const EdgeInsets.all(8.0),
 | 
					 | 
				
			||||||
                      child: ListTile(
 | 
					                      child: ListTile(
 | 
				
			||||||
                        shape: const RoundedRectangleBorder(
 | 
					                        shape: const RoundedRectangleBorder(
 | 
				
			||||||
                          borderRadius: BorderRadius.all(Radius.circular(8.0)),
 | 
					                          borderRadius: BorderRadius.all(Radius.circular(8.0)),
 | 
				
			||||||
@@ -140,13 +154,19 @@ class BotsScreen extends HookConsumerWidget {
 | 
				
			|||||||
                              ],
 | 
					                              ],
 | 
				
			||||||
                          onSelected: (value) {
 | 
					                          onSelected: (value) {
 | 
				
			||||||
                            if (value == 'edit') {
 | 
					                            if (value == 'edit') {
 | 
				
			||||||
                              context.pushNamed(
 | 
					                              showModalBottomSheet(
 | 
				
			||||||
                                'developerBotEdit',
 | 
					                                context: context,
 | 
				
			||||||
                                pathParameters: {
 | 
					                                isScrollControlled: true,
 | 
				
			||||||
                                  'name': publisherName,
 | 
					                                builder:
 | 
				
			||||||
                                  'projectId': projectId,
 | 
					                                    (context) => SheetScaffold(
 | 
				
			||||||
                                  'id': bot.id,
 | 
					                                      titleText: 'editBot'.tr(),
 | 
				
			||||||
                                },
 | 
					                                      child: EditBotScreen(
 | 
				
			||||||
 | 
					                                        publisherName: publisherName,
 | 
				
			||||||
 | 
					                                        projectId: projectId,
 | 
				
			||||||
 | 
					                                        id: bot.id,
 | 
				
			||||||
 | 
					                                        isModal: true,
 | 
				
			||||||
 | 
					                                      ),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
                              );
 | 
					                              );
 | 
				
			||||||
                            } else if (value == 'delete') {
 | 
					                            } else if (value == 'delete') {
 | 
				
			||||||
                              showConfirmAlert(
 | 
					                              showConfirmAlert(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,11 +38,13 @@ class EditBotScreen extends HookConsumerWidget {
 | 
				
			|||||||
  final String publisherName;
 | 
					  final String publisherName;
 | 
				
			||||||
  final String projectId;
 | 
					  final String projectId;
 | 
				
			||||||
  final String? id;
 | 
					  final String? id;
 | 
				
			||||||
 | 
					  final bool isModal;
 | 
				
			||||||
  const EditBotScreen({
 | 
					  const EditBotScreen({
 | 
				
			||||||
    super.key,
 | 
					    super.key,
 | 
				
			||||||
    required this.publisherName,
 | 
					    required this.publisherName,
 | 
				
			||||||
    required this.projectId,
 | 
					    required this.projectId,
 | 
				
			||||||
    this.id,
 | 
					    this.id,
 | 
				
			||||||
 | 
					    this.isModal = false,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
@@ -191,230 +193,293 @@ class EditBotScreen extends HookConsumerWidget {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final bodyContent =
 | 
				
			||||||
 | 
					        botData == null && !isNew
 | 
				
			||||||
 | 
					            ? const Center(child: CircularProgressIndicator())
 | 
				
			||||||
 | 
					            : botData?.hasError == true && !isNew
 | 
				
			||||||
 | 
					            ? ResponseErrorWidget(
 | 
				
			||||||
 | 
					              error: botData!.error,
 | 
				
			||||||
 | 
					              onRetry:
 | 
				
			||||||
 | 
					                  () => ref.invalidate(
 | 
				
			||||||
 | 
					                    botProvider(publisherName, projectId, id!),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            : SingleChildScrollView(
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  AspectRatio(
 | 
				
			||||||
 | 
					                    aspectRatio: 16 / 7,
 | 
				
			||||||
 | 
					                    child: Stack(
 | 
				
			||||||
 | 
					                      clipBehavior: Clip.none,
 | 
				
			||||||
 | 
					                      fit: StackFit.expand,
 | 
				
			||||||
 | 
					                      children: [
 | 
				
			||||||
 | 
					                        GestureDetector(
 | 
				
			||||||
 | 
					                          child: Container(
 | 
				
			||||||
 | 
					                            color:
 | 
				
			||||||
 | 
					                                Theme.of(
 | 
				
			||||||
 | 
					                                  context,
 | 
				
			||||||
 | 
					                                ).colorScheme.surfaceContainerHigh,
 | 
				
			||||||
 | 
					                            child:
 | 
				
			||||||
 | 
					                                background.value != null
 | 
				
			||||||
 | 
					                                    ? CloudFileWidget(
 | 
				
			||||||
 | 
					                                      item: background.value!,
 | 
				
			||||||
 | 
					                                      fit: BoxFit.cover,
 | 
				
			||||||
 | 
					                                    )
 | 
				
			||||||
 | 
					                                    : const SizedBox.shrink(),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                          onTap: () {
 | 
				
			||||||
 | 
					                            setPicture('background');
 | 
				
			||||||
 | 
					                          },
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        Positioned(
 | 
				
			||||||
 | 
					                          left: 20,
 | 
				
			||||||
 | 
					                          bottom: -32,
 | 
				
			||||||
 | 
					                          child: GestureDetector(
 | 
				
			||||||
 | 
					                            child: ProfilePictureWidget(
 | 
				
			||||||
 | 
					                              fileId: picture.value?.id,
 | 
				
			||||||
 | 
					                              radius: 40,
 | 
				
			||||||
 | 
					                              fallbackIcon: Symbols.smart_toy,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            onTap: () {
 | 
				
			||||||
 | 
					                              setPicture('picture');
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ],
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ).padding(bottom: 32),
 | 
				
			||||||
 | 
					                  Form(
 | 
				
			||||||
 | 
					                    key: formKey,
 | 
				
			||||||
 | 
					                    child: Column(
 | 
				
			||||||
 | 
					                      children: [
 | 
				
			||||||
 | 
					                        TextFormField(
 | 
				
			||||||
 | 
					                          controller: nameController,
 | 
				
			||||||
 | 
					                          decoration: InputDecoration(
 | 
				
			||||||
 | 
					                            labelText: 'name'.tr(),
 | 
				
			||||||
 | 
					                            border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                              borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                Radius.circular(12),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        TextFormField(
 | 
				
			||||||
 | 
					                          controller: nickController,
 | 
				
			||||||
 | 
					                          decoration: InputDecoration(
 | 
				
			||||||
 | 
					                            labelText: 'nickname'.tr(),
 | 
				
			||||||
 | 
					                            alignLabelWithHint: true,
 | 
				
			||||||
 | 
					                            border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                              borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                Radius.circular(12),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        TextFormField(
 | 
				
			||||||
 | 
					                          controller: slugController,
 | 
				
			||||||
 | 
					                          decoration: InputDecoration(
 | 
				
			||||||
 | 
					                            labelText: 'slug'.tr(),
 | 
				
			||||||
 | 
					                            helperText: 'slugHint'.tr(),
 | 
				
			||||||
 | 
					                            border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                              borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                Radius.circular(12),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        TextFormField(
 | 
				
			||||||
 | 
					                          controller: bioController,
 | 
				
			||||||
 | 
					                          decoration: InputDecoration(
 | 
				
			||||||
 | 
					                            labelText: 'bio'.tr(),
 | 
				
			||||||
 | 
					                            alignLabelWithHint: true,
 | 
				
			||||||
 | 
					                            border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                              borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                Radius.circular(12),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                          maxLines: 3,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        Row(
 | 
				
			||||||
 | 
					                          spacing: 16,
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: firstNameController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'firstName'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: middleNameController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'middleName'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: lastNameController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'lastName'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        Row(
 | 
				
			||||||
 | 
					                          spacing: 16,
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: genderController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'gender'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: pronounsController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'pronouns'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        Row(
 | 
				
			||||||
 | 
					                          spacing: 16,
 | 
				
			||||||
 | 
					                          children: [
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: locationController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'location'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            Expanded(
 | 
				
			||||||
 | 
					                              child: TextFormField(
 | 
				
			||||||
 | 
					                                controller: timeZoneController,
 | 
				
			||||||
 | 
					                                decoration: InputDecoration(
 | 
				
			||||||
 | 
					                                  labelText: 'timeZone'.tr(),
 | 
				
			||||||
 | 
					                                  border: OutlineInputBorder(
 | 
				
			||||||
 | 
					                                    borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                      Radius.circular(12),
 | 
				
			||||||
 | 
					                                    ),
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ],
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        GestureDetector(
 | 
				
			||||||
 | 
					                          onTap: () async {
 | 
				
			||||||
 | 
					                            final date = await showDatePicker(
 | 
				
			||||||
 | 
					                              context: context,
 | 
				
			||||||
 | 
					                              initialDate: birthday.value ?? DateTime.now(),
 | 
				
			||||||
 | 
					                              firstDate: DateTime(1900),
 | 
				
			||||||
 | 
					                              lastDate: DateTime.now(),
 | 
				
			||||||
 | 
					                            );
 | 
				
			||||||
 | 
					                            if (date != null) {
 | 
				
			||||||
 | 
					                              birthday.value = date;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                          },
 | 
				
			||||||
 | 
					                          child: Container(
 | 
				
			||||||
 | 
					                            padding: const EdgeInsets.all(16),
 | 
				
			||||||
 | 
					                            decoration: BoxDecoration(
 | 
				
			||||||
 | 
					                              border: Border.all(
 | 
				
			||||||
 | 
					                                color: Theme.of(context).dividerColor,
 | 
				
			||||||
 | 
					                                width: 1,
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                              borderRadius: BorderRadius.all(
 | 
				
			||||||
 | 
					                                Radius.circular(12),
 | 
				
			||||||
 | 
					                              ),
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                            child: Column(
 | 
				
			||||||
 | 
					                              crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
				
			||||||
 | 
					                              children: [
 | 
				
			||||||
 | 
					                                Text(
 | 
				
			||||||
 | 
					                                  'birthday'.tr(),
 | 
				
			||||||
 | 
					                                  style: TextStyle(
 | 
				
			||||||
 | 
					                                    color: Theme.of(context).hintColor,
 | 
				
			||||||
 | 
					                                  ),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                                Text(
 | 
				
			||||||
 | 
					                                  birthday.value != null
 | 
				
			||||||
 | 
					                                      ? DateFormat.yMMMd().format(
 | 
				
			||||||
 | 
					                                        birthday.value!,
 | 
				
			||||||
 | 
					                                      )
 | 
				
			||||||
 | 
					                                      : 'Select a date'.tr(),
 | 
				
			||||||
 | 
					                                ),
 | 
				
			||||||
 | 
					                              ],
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                        const SizedBox(height: 16),
 | 
				
			||||||
 | 
					                        Align(
 | 
				
			||||||
 | 
					                          alignment: Alignment.centerRight,
 | 
				
			||||||
 | 
					                          child: TextButton.icon(
 | 
				
			||||||
 | 
					                            onPressed: submitting.value ? null : performAction,
 | 
				
			||||||
 | 
					                            label: Text('saveChanges').tr(),
 | 
				
			||||||
 | 
					                            icon: const Icon(Symbols.save),
 | 
				
			||||||
 | 
					                          ),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ],
 | 
				
			||||||
 | 
					                    ).padding(all: 24),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (isModal) {
 | 
				
			||||||
 | 
					      return bodyContent;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return AppScaffold(
 | 
					    return AppScaffold(
 | 
				
			||||||
      isNoBackground: false,
 | 
					      isNoBackground: false,
 | 
				
			||||||
      appBar: AppBar(title: Text(isNew ? 'createBot'.tr() : 'editBot'.tr())),
 | 
					      appBar: AppBar(title: Text(isNew ? 'createBot'.tr() : 'editBot'.tr())),
 | 
				
			||||||
      body:
 | 
					      body: bodyContent,
 | 
				
			||||||
          botData == null && !isNew
 | 
					 | 
				
			||||||
              ? const Center(child: CircularProgressIndicator())
 | 
					 | 
				
			||||||
              : botData?.hasError == true && !isNew
 | 
					 | 
				
			||||||
              ? ResponseErrorWidget(
 | 
					 | 
				
			||||||
                error: botData!.error,
 | 
					 | 
				
			||||||
                onRetry:
 | 
					 | 
				
			||||||
                    () => ref.invalidate(
 | 
					 | 
				
			||||||
                      botProvider(publisherName, projectId, id!),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
              )
 | 
					 | 
				
			||||||
              : SingleChildScrollView(
 | 
					 | 
				
			||||||
                child: Column(
 | 
					 | 
				
			||||||
                  children: [
 | 
					 | 
				
			||||||
                    AspectRatio(
 | 
					 | 
				
			||||||
                      aspectRatio: 16 / 7,
 | 
					 | 
				
			||||||
                      child: Stack(
 | 
					 | 
				
			||||||
                        clipBehavior: Clip.none,
 | 
					 | 
				
			||||||
                        fit: StackFit.expand,
 | 
					 | 
				
			||||||
                        children: [
 | 
					 | 
				
			||||||
                          GestureDetector(
 | 
					 | 
				
			||||||
                            child: Container(
 | 
					 | 
				
			||||||
                              color:
 | 
					 | 
				
			||||||
                                  Theme.of(
 | 
					 | 
				
			||||||
                                    context,
 | 
					 | 
				
			||||||
                                  ).colorScheme.surfaceContainerHigh,
 | 
					 | 
				
			||||||
                              child:
 | 
					 | 
				
			||||||
                                  background.value != null
 | 
					 | 
				
			||||||
                                      ? CloudFileWidget(
 | 
					 | 
				
			||||||
                                        item: background.value!,
 | 
					 | 
				
			||||||
                                        fit: BoxFit.cover,
 | 
					 | 
				
			||||||
                                      )
 | 
					 | 
				
			||||||
                                      : const SizedBox.shrink(),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                            onTap: () {
 | 
					 | 
				
			||||||
                              setPicture('background');
 | 
					 | 
				
			||||||
                            },
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          Positioned(
 | 
					 | 
				
			||||||
                            left: 20,
 | 
					 | 
				
			||||||
                            bottom: -32,
 | 
					 | 
				
			||||||
                            child: GestureDetector(
 | 
					 | 
				
			||||||
                              child: ProfilePictureWidget(
 | 
					 | 
				
			||||||
                                fileId: picture.value?.id,
 | 
					 | 
				
			||||||
                                radius: 40,
 | 
					 | 
				
			||||||
                                fallbackIcon: Symbols.smart_toy,
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              onTap: () {
 | 
					 | 
				
			||||||
                                setPicture('picture');
 | 
					 | 
				
			||||||
                              },
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ],
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                    ).padding(bottom: 32),
 | 
					 | 
				
			||||||
                    Form(
 | 
					 | 
				
			||||||
                      key: formKey,
 | 
					 | 
				
			||||||
                      child: Column(
 | 
					 | 
				
			||||||
                        children: [
 | 
					 | 
				
			||||||
                          TextFormField(
 | 
					 | 
				
			||||||
                            controller: nameController,
 | 
					 | 
				
			||||||
                            decoration: InputDecoration(labelText: 'name'.tr()),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          TextFormField(
 | 
					 | 
				
			||||||
                            controller: nickController,
 | 
					 | 
				
			||||||
                            decoration: InputDecoration(
 | 
					 | 
				
			||||||
                              labelText: 'nickname'.tr(),
 | 
					 | 
				
			||||||
                              alignLabelWithHint: true,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          TextFormField(
 | 
					 | 
				
			||||||
                            controller: slugController,
 | 
					 | 
				
			||||||
                            decoration: InputDecoration(
 | 
					 | 
				
			||||||
                              labelText: 'slug'.tr(),
 | 
					 | 
				
			||||||
                              helperText: 'slugHint'.tr(),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          TextFormField(
 | 
					 | 
				
			||||||
                            controller: bioController,
 | 
					 | 
				
			||||||
                            decoration: InputDecoration(
 | 
					 | 
				
			||||||
                              labelText: 'bio'.tr(),
 | 
					 | 
				
			||||||
                              alignLabelWithHint: true,
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                            maxLines: 3,
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          Row(
 | 
					 | 
				
			||||||
                            spacing: 16,
 | 
					 | 
				
			||||||
                            children: [
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: firstNameController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'firstName'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: middleNameController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'middleName'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: lastNameController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'lastName'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          Row(
 | 
					 | 
				
			||||||
                            spacing: 16,
 | 
					 | 
				
			||||||
                            children: [
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: genderController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'gender'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: pronounsController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'pronouns'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          Row(
 | 
					 | 
				
			||||||
                            spacing: 16,
 | 
					 | 
				
			||||||
                            children: [
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: locationController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'location'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              Expanded(
 | 
					 | 
				
			||||||
                                child: TextFormField(
 | 
					 | 
				
			||||||
                                  controller: timeZoneController,
 | 
					 | 
				
			||||||
                                  decoration: InputDecoration(
 | 
					 | 
				
			||||||
                                    labelText: 'timeZone'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          GestureDetector(
 | 
					 | 
				
			||||||
                            onTap: () async {
 | 
					 | 
				
			||||||
                              final date = await showDatePicker(
 | 
					 | 
				
			||||||
                                context: context,
 | 
					 | 
				
			||||||
                                initialDate: birthday.value ?? DateTime.now(),
 | 
					 | 
				
			||||||
                                firstDate: DateTime(1900),
 | 
					 | 
				
			||||||
                                lastDate: DateTime.now(),
 | 
					 | 
				
			||||||
                              );
 | 
					 | 
				
			||||||
                              if (date != null) {
 | 
					 | 
				
			||||||
                                birthday.value = date;
 | 
					 | 
				
			||||||
                              }
 | 
					 | 
				
			||||||
                            },
 | 
					 | 
				
			||||||
                            child: Container(
 | 
					 | 
				
			||||||
                              padding: const EdgeInsets.symmetric(vertical: 8),
 | 
					 | 
				
			||||||
                              decoration: BoxDecoration(
 | 
					 | 
				
			||||||
                                border: Border(
 | 
					 | 
				
			||||||
                                  bottom: BorderSide(
 | 
					 | 
				
			||||||
                                    color: Theme.of(context).dividerColor,
 | 
					 | 
				
			||||||
                                    width: 1,
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                              child: Column(
 | 
					 | 
				
			||||||
                                crossAxisAlignment: CrossAxisAlignment.stretch,
 | 
					 | 
				
			||||||
                                children: [
 | 
					 | 
				
			||||||
                                  Text(
 | 
					 | 
				
			||||||
                                    'birthday'.tr(),
 | 
					 | 
				
			||||||
                                    style: TextStyle(
 | 
					 | 
				
			||||||
                                      color: Theme.of(context).hintColor,
 | 
					 | 
				
			||||||
                                    ),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                  Text(
 | 
					 | 
				
			||||||
                                    birthday.value != null
 | 
					 | 
				
			||||||
                                        ? DateFormat.yMMMd().format(
 | 
					 | 
				
			||||||
                                          birthday.value!,
 | 
					 | 
				
			||||||
                                        )
 | 
					 | 
				
			||||||
                                        : 'Select a date'.tr(),
 | 
					 | 
				
			||||||
                                  ),
 | 
					 | 
				
			||||||
                                ],
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          const SizedBox(height: 16),
 | 
					 | 
				
			||||||
                          Align(
 | 
					 | 
				
			||||||
                            alignment: Alignment.centerRight,
 | 
					 | 
				
			||||||
                            child: TextButton.icon(
 | 
					 | 
				
			||||||
                              onPressed:
 | 
					 | 
				
			||||||
                                  submitting.value ? null : performAction,
 | 
					 | 
				
			||||||
                              label: Text('saveChanges').tr(),
 | 
					 | 
				
			||||||
                              icon: const Icon(Symbols.save),
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ],
 | 
					 | 
				
			||||||
                      ).padding(all: 24),
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ],
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +1,23 @@
 | 
				
			|||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:island/screens/developers/edit_bot.dart';
 | 
					import 'package:island/screens/developers/edit_bot.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NewBotScreen extends StatelessWidget {
 | 
					class NewBotScreen extends StatelessWidget {
 | 
				
			||||||
  final String publisherName;
 | 
					  final String publisherName;
 | 
				
			||||||
  final String projectId;
 | 
					  final String projectId;
 | 
				
			||||||
  const NewBotScreen({super.key, required this.publisherName, required this.projectId});
 | 
					  final bool isModal;
 | 
				
			||||||
 | 
					  const NewBotScreen({
 | 
				
			||||||
 | 
					    super.key,
 | 
				
			||||||
 | 
					    required this.publisherName,
 | 
				
			||||||
 | 
					    required this.projectId,
 | 
				
			||||||
 | 
					    this.isModal = false,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return EditBotScreen(publisherName: publisherName, projectId: projectId);
 | 
					    return EditBotScreen(
 | 
				
			||||||
 | 
					      publisherName: publisherName,
 | 
				
			||||||
 | 
					      projectId: projectId,
 | 
				
			||||||
 | 
					      isModal: isModal,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,8 +58,8 @@ class ProjectDetailView extends HookConsumerWidget {
 | 
				
			|||||||
                leading: Container(
 | 
					                leading: Container(
 | 
				
			||||||
                  width: 256,
 | 
					                  width: 256,
 | 
				
			||||||
                  padding: EdgeInsets.only(
 | 
					                  padding: EdgeInsets.only(
 | 
				
			||||||
                    left: 16,
 | 
					                    left: 24,
 | 
				
			||||||
                    right: 16,
 | 
					                    right: 24,
 | 
				
			||||||
                    bottom: 8,
 | 
					                    bottom: 8,
 | 
				
			||||||
                    top: 2,
 | 
					                    top: 2,
 | 
				
			||||||
                  ),
 | 
					                  ),
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user