fist commit ftc staff app clone

This commit is contained in:
2024-08-01 13:46:46 +05:30
commit bf9064a9c9
515 changed files with 42796 additions and 0 deletions

View File

@@ -0,0 +1,203 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/models/clients/memoryListResponse/MemoryListData.dart';
import 'package:ftc_mobile_app/models/profileData/user_data.dart';
import 'package:ftc_mobile_app/view/custom_widgets/my_network_image.dart';
import 'package:get/get.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'controller/add_edit_memory_box_screen_controller.dart';
import 'widget/VideoPlayerWidget.dart';
class AddEditMemoryBoxScreenArgs {
final UserData userData;
final MemoryListData? data;
final bool viewOnly;
AddEditMemoryBoxScreenArgs({
required this.userData,
this.data,
this.viewOnly = false,
});
}
//This screen is used to view, add and edit memory box
class AddEditMemoryBoxScreen extends StatefulWidget {
final AddEditMemoryBoxScreenArgs args;
const AddEditMemoryBoxScreen({super.key, required this.args});
@override
State<AddEditMemoryBoxScreen> createState() => _AddEditMemoryBoxScreenState();
}
class _AddEditMemoryBoxScreenState extends State<AddEditMemoryBoxScreen> {
final controller = Get.put(AddEditMemoryBoxScreenController());
@override
void initState() {
controller.serviceUserId = widget.args.userData.id!;
if (forUpdate) {
controller.filePath.value =
'${WebUrls.baseUrl}${widget.args.data!.filePath ?? ""}';
controller.noteDetailsController.text = widget.args.data!.note ?? "";
}
super.initState();
}
bool get forUpdate => widget.args.data != null;
@override
Widget build(BuildContext context) {
return CustomScaffold(
backgroundColor: CustomAppColors.kPrimaryColor,
screenKey: controller.screenKey,
onScreenTap: controller.removeFocus,
showAppBar: true,
appBar: CustomAppBarTitleOnly(
context,
titleText:
"${widget.args.viewOnly ? "View" : forUpdate ? "Update" : "Add"} Memory Box",
),
body: SafeArea(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20.r),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: (widget.args.viewOnly)
? _viewOnlyWidgets
: [
12.verticalSpace,
Obx(() {
final path = controller.filePath();
return mediaViewer(path: path);
}),
CustomTextWidget(
text: "Upload File",
textAlign: TextAlign.left,
fontSize: 16.sp,
fontColor: Colors.black,
fontWeight: FontWeight.w600,
),
// CustomTextWidget(
// text: "Please upload a file that is 1MB or smaller.",
// textAlign: TextAlign.left,
// fontSize: 12.sp,
// fontColor: Colors.grey,
// ),
12.verticalSpace,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
flex: 1,
child: SizedBox(
height: 32.r,
child: CustomAppButton(
buttonColor: Get.theme.primaryColor,
buttonText: "Choose File",
onTap: controller.onFileChooseButtonTap,
),
).paddingOnly(right: 8.r),
),
Expanded(
flex: 2,
child: Obx(() {
return controller.filePath.isNotEmpty
? Obx(
() => CustomTextWidget(
text: controller.filePath.value
.split("/")
.last,
isExpanded: false,
textAlign: TextAlign.left,
),
)
: FrequentFunctions.noWidget;
}),
),
],
),
20.verticalSpace,
CustomTextFieldWidget(
borderRadius: BorderRadius.circular(10.r),
borderColor: CustomAppColors.kLightGreyColor,
controller: controller.noteDetailsController,
heading: "Note Details",
hintText: "Type here...",
minLines: 6,
maxLines: 6,
onChange: (_) {},
),
32.verticalSpace,
CustomAppButton(
buttonText: forUpdate ? "Update" : "Save",
onTap: () {
forUpdate
? controller
.updateButtonPress(widget.args.data!.id!)
: controller.saveButtonPress();
},
),
5.verticalSpace,
],
),
),
),
),
);
}
List<Widget> get _viewOnlyWidgets {
return [
12.verticalSpace,
mediaViewer(
path: '${WebUrls.baseUrl}${widget.args.data?.filePath ?? ""}'),
20.verticalSpace,
Column(
children: [
CustomTextWidget(
text: "Note Details",
textAlign: TextAlign.left,
fontSize: 16.sp,
fontWeight: FontWeight.w600,
fontColor: Colors.black,
),
CustomTextWidget(
text: widget.args.data?.note ?? "",
textAlign: TextAlign.left,
fontSize: 14.sp,
fontColor: Colors.black,
),
],
)
];
}
Widget mediaViewer({required String path}) {
if (path.isVideoFileName) {
return VideoPlayerWidget(
path: path,
type: path.startsWith("http")
? VideoSourceType.network
: VideoSourceType.file,
);
} else if (path.isImageFileName) {
if (path.startsWith("http")) {
return MyNetworkImage(url: path);
} else {
return Image.file(File(path));
}
} else {
return FrequentFunctions.noWidget;
}
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}

View File

@@ -0,0 +1,98 @@
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:ftc_mobile_app/utilities/extensions/custom_extensions.dart';
import 'package:ftc_mobile_app/utilities/frequent_functions.dart';
import 'package:ftc_mobile_app/web_services/client_services.dart';
import 'package:get/get.dart';
class AddEditMemoryBoxScreenController extends GetxController {
final GlobalKey<ScaffoldState> screenKey = GlobalKey<ScaffoldState>();
TextEditingController documentTitleController = TextEditingController();
TextEditingController noteDetailsController = TextEditingController();
late final String serviceUserId;
final file = Rx<File?>(null);
//Should stores full path of file or url
final filePath = "".obs;
onFileChooseButtonTap() async {
FilePickerResult? result =
await FilePicker.platform.pickFiles(type: FileType.media);
if (result != null && result.files.single.path != null) {
if (result.files.single.path!.isVideoFileName ||
result.files.single.path!.isImageFileName) {
file.value = File(result.files.single.path!);
filePath.value = result.files.single.path!;
} else {
FrequentFunctions.showToast(message: "Unsupported File");
}
}
}
Future<void> saveButtonPress() async {
if (file() == null) {
FrequentFunctions.showToast(message: "Please select file first");
return;
}
if (noteDetailsController.text.trim().isEmpty) {
FrequentFunctions.showToast(message: "Note details field is required");
return;
}
var response = await ClientService()
.addMemoryBoxFile(
userId: serviceUserId,
filePath: file.value!.path,
noteDetails: noteDetailsController.text,
)
.showLoader();
if (response == true) {
backButtonPressed(argument: true);
} else {
FrequentFunctions.showToast(message: response);
}
}
Future<void> updateButtonPress(String id) async {
if (noteDetailsController.text.trim().isEmpty) {
FrequentFunctions.showToast(message: "Note details field is required");
return;
}
var response = await ClientService()
.updateMemoryBoxFile(
id: id,
userId: serviceUserId,
filePath: file.value?.path ?? "",
noteDetails: noteDetailsController.text,
)
.showLoader();
if (response == true) {
backButtonPressed(argument: true);
} else {
FrequentFunctions.showToast(message: response);
}
}
void backButtonPressed({dynamic argument}) {
Navigator.of(screenKey.currentContext!).pop(argument);
}
void removeFocus() {
FocusScope.of(screenKey.currentContext!).unfocus();
}
@override
void dispose() {
noteDetailsController.dispose();
Get.delete<AddEditMemoryBoxScreenController>();
super.dispose();
}
}

View File

@@ -0,0 +1,93 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:ftc_mobile_app/ftc_mobile_app.dart';
import 'package:video_player/video_player.dart';
enum VideoSourceType { file, network }
class VideoPlayerWidget extends StatefulWidget {
final String path;
final VideoSourceType type;
const VideoPlayerWidget({
super.key,
required this.path,
required this.type,
});
@override
State<VideoPlayerWidget> createState() => _VideoPlayerWidgetState();
}
class _VideoPlayerWidgetState extends State<VideoPlayerWidget> {
VideoPlayerController? _videoPlayerController;
final RxBool isInitialized = false.obs;
final RxBool isError = false.obs;
final RxBool isPlaying = false.obs;
double aspectRatio = 16.0 / 9.0;
@override
void initState() {
print("Video path: ${widget.path}");
if (widget.type == VideoSourceType.network) {
print("VideoSourceType.network");
_videoPlayerController =
VideoPlayerController.networkUrl(Uri.parse(widget.path));
} else {
print("VideoSourceType.file");
_videoPlayerController = VideoPlayerController.file(File(widget.path));
}
_videoPlayerController?.initialize().then((_) {
isInitialized.value = true;
});
super.initState();
}
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: aspectRatio,
child: Obx(() {
return (isError())
? FrequentFunctions.centerText(text: "Something went wrong")
: isInitialized.isFalse
? FrequentFunctions.centerText(text: "Loading video...")
: Stack(
children: [
Positioned.fill(
child: VideoPlayer(_videoPlayerController!),
),
Center(
child: Obx(() {
return (isPlaying())
? FrequentFunctions.noWidget
: InkWell(
onTap: () {
if (isPlaying.isFalse) {
isPlaying.value = true;
_videoPlayerController?.play();
}
},
child: Icon(
Icons.play_circle,
color: Get.theme.primaryColor,
size: 56.r,
),
);
}),
)
],
);
}),
);
}
@override
void dispose() {
_videoPlayerController?.dispose();
_videoPlayerController = null;
super.dispose();
}
}