Skip to content

Commit

Permalink
[PDA-44] feat: 비품 추가 UI 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
chayoosang committed Dec 2, 2023
1 parent 565bba0 commit 887bf4f
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 23 deletions.
5 changes: 5 additions & 0 deletions asset/image/image_plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ PODS:
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (7.11.6):
- GoogleUtilities/Logger
- image_picker_ios (0.0.1):
- Flutter
- nanopb (2.30909.1):
- nanopb/decode (= 2.30909.1)
- nanopb/encode (= 2.30909.1)
Expand All @@ -77,6 +79,7 @@ DEPENDENCIES:
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)

SPEC REPOS:
Expand Down Expand Up @@ -105,6 +108,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
fluttertoast:
:path: ".symlinks/plugins/fluttertoast/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"

Expand All @@ -122,6 +127,7 @@ SPEC CHECKSUMS:
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2
GoogleUtilities: 202e7a9f5128accd11160fb9c19612de1911aa19
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
Expand Down
6 changes: 6 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPhotoLibraryUsageDescription</key>
<string>사진 추가를 위해 사진 접근 허용을 해주세요.</string>
<key>NSCameraUsageDescription</key>
<string>사진 추가를 위해 카메라 접근 허용을 해주세요.</string>
<key>NSMicrophoneUsageDescription</key>
<string>마이크 권한 좀요</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
Expand Down
30 changes: 30 additions & 0 deletions lib/Model/model/equipment/equipment_category_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:frontend/Model/model/general_model.dart';
import 'package:json_annotation/json_annotation.dart';

part 'equipment_category_model.g.dart';

@JsonSerializable()
class EquipmentCategoryResponseModel extends GeneralModel {
final EquipmentCategory data;

EquipmentCategoryResponseModel(
{required super.status,
required super.code,
required super.message,
required this.data});

factory EquipmentCategoryResponseModel.fromJson(Map<String, dynamic> json) =>
_$EquipmentCategoryResponseModelFromJson(json);
}

@JsonSerializable()
class EquipmentCategory {
List<String> categoryNames;

EquipmentCategory({
required this.categoryNames,
});

factory EquipmentCategory.fromJson(Map<String, dynamic> json) =>
_$EquipmentCategoryFromJson(json);
}
37 changes: 37 additions & 0 deletions lib/Model/model/equipment/equipment_category_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions lib/Presenter/equipment/equipment_service.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import 'package:dio/dio.dart';
import 'package:frontend/Model/model/equipment/equipment_category_model.dart';
import 'package:frontend/Model/model/general_model.dart';
import 'package:frontend/Model/network/api_manager.dart';

class EquipmentService {
final equipmentURL = '/equipments?cond=';
final equipmentCategoryURL = "/equipments/categories";

static final EquipmentService _equipmentService = EquipmentService._();
EquipmentService._();
Expand All @@ -16,8 +20,8 @@ class EquipmentService {
}

Future<dynamic> getEquipmentCategory() async {
final response =
APIManager().request(RequestType.get, equipmentURL, null, null, null);
final response = APIManager()
.request(RequestType.get, equipmentCategoryURL, null, null, null);
return response;
}
}
115 changes: 94 additions & 21 deletions lib/View/equipment/screen/equipment_add_screen.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:frontend/Model/model/equipment/equipment_category_model.dart';
import 'package:frontend/Presenter/equipment/equipment_service.dart';
import 'package:frontend/View/common/component/purple_bottom_button.dart';
import 'package:frontend/View/common/component/sub_app_bar.dart';
import 'package:image_picker/image_picker.dart';

class EquipmentAddScreen extends StatefulWidget {
const EquipmentAddScreen({super.key});
Expand All @@ -9,7 +16,8 @@ class EquipmentAddScreen extends StatefulWidget {
}

class _EquipmentAddScreen extends State<EquipmentAddScreen> {
final categories = ["1", "2", "3"];
var categories = [""];
var userImage;
String? _selectedCategory;
FocusNode nameFocusNode = FocusNode();
FocusNode quantityFocusNode = FocusNode();
Expand Down Expand Up @@ -41,10 +49,48 @@ class _EquipmentAddScreen extends State<EquipmentAddScreen> {
appBar: const SubAppBar(
titleText: '신규 비품 추가',
),
body: renderBody(),
body: futureBody(),
bottomNavigationBar: PurpleBottomButton(
title: '추가',
onPressed: equipmentAdd,
),
);
}

Widget futureBody() {
return FutureBuilder(
future: EquipmentService().getEquipmentCategory(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return notCategoryBody();
}

if (snapshot.hasData) {
categories = EquipmentCategoryResponseModel.fromJson(snapshot.data)
.data
.categoryNames;
if (categories.isEmpty) {
return notCategoryBody();
} else {
return renderBody();
}
} else {
return const CircularProgressIndicator();
}
});
}

Widget notCategoryBody() {
return Center(
child: Container(
width: double.infinity,
height: double.infinity,
alignment: Alignment.center,
child: const Text("카테고리 목록이 없습니다.\n다시 시도해주세요.",
style: TextStyle(fontSize: 16, color: Colors.purple)),
));
}

Widget renderBody() {
return Container(
margin: const EdgeInsets.only(top: 14, right: 20, left: 20),
Expand Down Expand Up @@ -193,18 +239,29 @@ class _EquipmentAddScreen extends State<EquipmentAddScreen> {
const SizedBox(
height: 14,
),
SizedBox(
Container(
width: double.infinity,
height: 42,
padding: const EdgeInsets.all(10),
clipBehavior: Clip.antiAlias,
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
side: const BorderSide(width: 1, color: Color(0xFF939393)),
borderRadius: BorderRadius.circular(10),
),
),
child: DropdownButton(
hint: const Text('카테고리를 선택해주세요.',
style: TextStyle(
color: Color(0xFFC9C9C9),
color: Color(0xFF4C4C4C),
fontSize: 13,
fontFamily: 'NanumSquare_ac',
fontWeight: FontWeight.w400,
height: 0,
)),
isExpanded: true,
underline: const SizedBox.shrink(),
value: _selectedCategory,
items: categories.map((category) {
return DropdownMenuItem(
Expand Down Expand Up @@ -310,26 +367,42 @@ class _EquipmentAddScreen extends State<EquipmentAddScreen> {
const SizedBox(
height: 14,
),
SizedBox(
width: double.infinity,
height: 42,
child: TextField(
maxLines: 1,
focusNode: nameFocusNode,
obscureText: false,
controller: nameController,
decoration: const InputDecoration(
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Color(0xFF640FAF))),
isDense: true,
hintText: "비품명을 입력해주세요.",
contentPadding: EdgeInsets.all(10)),
),
),
Row(
children: [
Container(
decoration: ShapeDecoration(
color: const Color(0xFFF6F6F6),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
width: 79,
height: 79,
child: IconButton(
icon: userImage == null
? SvgPicture.asset('asset/image/image_plus.svg')
: Image.file(
userImage,
fit: BoxFit.fill,
),
onPressed: imageAdd,
)),
],
)
],
),
);
}

void moveToAddEquipment() {}
void imageAdd() async {
var picker = ImagePicker();
var image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
setState(() {
userImage = File(image.path);
});
}
}

void equipmentAdd() {}
}
Loading

0 comments on commit 887bf4f

Please sign in to comment.