Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#71 仕事詳細ページの実装 #88

Merged
merged 5 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/dart_flutter_common/lib/dart_flutter_common.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export 'src/components/_export.dart';
export 'src/date_time.dart';
export 'src/image_detail_view.dart';
export 'src/int.dart';
export 'src/pick_image.dart';
export 'src/scaffold_messenger_controller.dart';
export 'src/section.dart';
export 'src/selectable_chips.dart';
export 'src/string.dart';
export 'src/image_detail_view.dart';
5 changes: 2 additions & 3 deletions packages/dart_flutter_common/lib/src/image_detail_view.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';

class DetailDisplayableImage extends StatelessWidget {
DetailDisplayableImage({
const DetailDisplayableImage({
required this.image,
super.key,
});
Expand Down Expand Up @@ -37,10 +37,9 @@ class DetailDisplayableImage extends StatelessWidget {

// 詳細画像表示
class _ImageDetailView extends StatelessWidget {
_ImageDetailView({
const _ImageDetailView({
required this.tag,
required this.image,
super.key,
});

final String tag;
Expand Down
79 changes: 79 additions & 0 deletions packages/dart_flutter_common/lib/src/section.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import 'package:flutter/material.dart';

/// - 必須: [title] タイトル文字列
/// - 任意: [description] 説明文字列
/// - 必須: [content] 内容を表すウィジェット
///
/// を上から順に並べて構成されるシンプルなセクションウィジェット。
class Section extends StatelessWidget {
const Section({
required this.title,
this.titleStyle,
this.titleMaxLines = 1,
this.titleBottomMargin = 16,
this.description,
this.descriptionStyle,
this.descriptionMaxLines,
this.descriptionBottomMargin = 16,
required this.content,
this.sectionPadding,
super.key,
});

/// セクションのタイトル。
final String title;

/// [title] のスタイル。
final TextStyle? titleStyle;

/// [title] の表示行数。
final int titleMaxLines;

/// [title] の下の余白。
final double titleBottomMargin;

/// セクションの説明。
final String? description;

/// [description] のスタイル。
final TextStyle? descriptionStyle;

/// [description] の最大行数。
final int? descriptionMaxLines;

/// [description] の下の余白
final double descriptionBottomMargin;

/// セクションのコンテンツ。
final Widget content;

/// セクション全体のパディング。
final EdgeInsetsGeometry? sectionPadding;

@override
Widget build(BuildContext context) {
return Padding(
padding: sectionPadding ?? EdgeInsets.zero,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: titleStyle,
maxLines: titleMaxLines,
),
SizedBox(height: titleBottomMargin),
if (description != null) ...[
Text(
description!,
style: descriptionStyle,
maxLines: descriptionMaxLines,
),
SizedBox(height: descriptionBottomMargin),
],
content,
],
),
);
}
}
87 changes: 87 additions & 0 deletions packages/dart_flutter_common/lib/src/selectable_chips.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'package:flutter/material.dart';

/// [Chip] ウィジェットを [Wrap] で囲んだ UI.
/// 画面端で改行する。
/// 引数として選択可能なすべての選択肢 [allItems] と
/// 実際に選択されている選択肢 [enabledItems] を受け取る。
/// オプションで選択されていないデータの表示非表示を選択可能である。
class SelectableChips<T> extends StatelessWidget {
const SelectableChips({
required this.allItems,
required this.labels,
required this.enabledItems,
this.chipPadding = const EdgeInsets.only(right: 8),
this.isDisplayDisable = true,
this.direction = Axis.horizontal,
this.alignment = WrapAlignment.start,
this.crossAxisAlignment = WrapCrossAlignment.start,
super.key,
});

/// 選択可能な選択肢。
final Iterable<T> allItems;

/// 選択肢をキーにしたデータのラベル。
final Map<T, String> labels;

/// 有効な選択肢。
final Iterable<T> enabledItems;

/// チップ一つのパディング。
final EdgeInsetsGeometry chipPadding;

/// [enabledItems] に含まれていないチップを非表示にするか否か。
final bool isDisplayDisable;

/// [Wrap] で並べる方向。
final Axis direction;

/// [direction] 方向の並び方。
final WrapAlignment alignment;

/// [direction] と垂直方向の並び方。
final WrapCrossAlignment crossAxisAlignment;

@override
Widget build(BuildContext context) {
return Wrap(
direction: direction,
alignment: alignment,
crossAxisAlignment: crossAxisAlignment,
children: allItems
.where(
(item) => enabledItems.contains(item) || isDisplayDisable,
)
.map(
(item) => Padding(
padding: chipPadding,
child: _SwitchingChip(
label: labels[item] ?? '',
isEnabled: enabledItems.contains(item),
),
),
)
.toList(),
);
}
}

class _SwitchingChip extends StatelessWidget {
const _SwitchingChip({
required this.label,
this.isEnabled = false,
});

final bool isEnabled;
final String label;

@override
Widget build(BuildContext context) {
return InputChip(
onPressed: () => {},
isEnabled: isEnabled,
side: isEnabled ? BorderSide.none : null,
label: Text(label),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:json_annotation/json_annotation.dart';

part 'job.flutterfire_gen.dart';

@FirestoreDocument(path: 'jobs', documentName: 'hostLocation')
@FirestoreDocument(path: 'jobs', documentName: 'jobs')
class Job {
const Job({
required this.hostId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ part of 'job.dart';

class ReadJob {
const ReadJob({
required this.hostLocationId,
required this.jobId,
required this.path,
required this.hostId,
required this.title,
Expand All @@ -22,7 +22,7 @@ class ReadJob {
required this.updatedAt,
});

final String hostLocationId;
final String jobId;

final String path;

Expand Down Expand Up @@ -52,7 +52,7 @@ class ReadJob {

factory ReadJob._fromJson(Map<String, dynamic> json) {
return ReadJob(
hostLocationId: json['hostLocationId'] as String,
jobId: json['jobId'] as String,
path: json['path'] as String,
hostId: json['hostId'] as String,
title: json['title'] as String? ?? '',
Expand Down Expand Up @@ -83,7 +83,7 @@ class ReadJob {
final data = ds.data()! as Map<String, dynamic>;
return ReadJob._fromJson(<String, dynamic>{
...data,
'hostLocationId': ds.id,
'jobId': ds.id,
'path': ds.reference.path,
});
}
Expand Down Expand Up @@ -197,9 +197,9 @@ final readJobCollectionReference =

/// A [DocumentReference] to hostLocation document to read.
DocumentReference<ReadJob> readJobDocumentReference({
required String hostLocationId,
required String jobId,
}) =>
readJobCollectionReference.doc(hostLocationId);
readJobCollectionReference.doc(jobId);

/// A [CollectionReference] to jobs collection to create.
final createJobCollectionReference =
Expand All @@ -210,9 +210,9 @@ final createJobCollectionReference =

/// A [DocumentReference] to hostLocation document to create.
DocumentReference<CreateJob> createJobDocumentReference({
required String hostLocationId,
required String jobId,
}) =>
createJobCollectionReference.doc(hostLocationId);
createJobCollectionReference.doc(jobId);

/// A [CollectionReference] to jobs collection to update.
final updateJobCollectionReference =
Expand All @@ -223,19 +223,19 @@ final updateJobCollectionReference =

/// A [DocumentReference] to hostLocation document to update.
DocumentReference<UpdateJob> updateJobDocumentReference({
required String hostLocationId,
required String jobId,
}) =>
updateJobCollectionReference.doc(hostLocationId);
updateJobCollectionReference.doc(jobId);

/// A [CollectionReference] to jobs collection to delete.
final deleteJobCollectionReference =
FirebaseFirestore.instance.collection('jobs');

/// A [DocumentReference] to hostLocation document to delete.
DocumentReference<Object?> deleteJobDocumentReference({
required String hostLocationId,
required String jobId,
}) =>
deleteJobCollectionReference.doc(hostLocationId);
deleteJobCollectionReference.doc(jobId);

/// A query manager to execute query against [Job].
class JobQuery {
Expand Down Expand Up @@ -284,23 +284,23 @@ class JobQuery {

/// Fetches a specified [ReadJob] document.
Future<ReadJob?> fetchDocument({
required String hostLocationId,
required String jobId,
GetOptions? options,
}) async {
final ds = await readJobDocumentReference(
hostLocationId: hostLocationId,
jobId: jobId,
).get(options);
return ds.data();
}

/// Subscribes a specified [Job] document.
Stream<ReadJob?> subscribeDocument({
required String hostLocationId,
required String jobId,
bool includeMetadataChanges = false,
bool excludePendingWrites = false,
}) {
var streamDs = readJobDocumentReference(
hostLocationId: hostLocationId,
jobId: jobId,
).snapshots(includeMetadataChanges: includeMetadataChanges);
if (excludePendingWrites) {
streamDs = streamDs.where((ds) => !ds.metadata.hasPendingWrites);
Expand All @@ -316,28 +316,28 @@ class JobQuery {

/// Sets a [Job] document.
Future<void> set({
required String hostLocationId,
required String jobId,
required CreateJob createJob,
SetOptions? options,
}) =>
createJobDocumentReference(
hostLocationId: hostLocationId,
jobId: jobId,
).set(createJob, options);

/// Updates a specified [Job] document.
Future<void> update({
required String hostLocationId,
required String jobId,
required UpdateJob updateJob,
}) =>
updateJobDocumentReference(
hostLocationId: hostLocationId,
jobId: jobId,
).update(updateJob.toJson());

/// Deletes a specified [Job] document.
Future<void> delete({
required String hostLocationId,
required String jobId,
}) =>
deleteJobDocumentReference(
hostLocationId: hostLocationId,
jobId: jobId,
).delete();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ import '../firestore_documents/job.dart';

class JobRepository {
final _query = JobQuery();

/// 指定した [Job] を取得する。
Future<ReadJob?> fetchJob({required String jobId}) =>
_query.fetchDocument(jobId: jobId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '../../../auth/auth.dart';
import '../../../auth/ui/sign_in_buttons.dart';
import '../../../chat/ui/chat_room.dart';
import '../../../force_update/ui/force_update.dart';
import '../../../job/ui/job_detail.dart';
import '../../../map/ui/map.dart';
import '../../../scaffold_messenger_controller.dart';
import '../../../user/user.dart';
Expand Down Expand Up @@ -60,15 +61,15 @@ class DevelopmentItemsPage extends ConsumerWidget {
),
),
),
const ListTile(
ListTile(
title: Text('仕事詳細ページ (FutureProvider)'),
// TODO: 後に auto_route を採用して Navigator.pushNamed を使用する予定
// onTap: () => Navigator.push<void>(
// context,
// MaterialPageRoute<void>(
// builder: (context) => FooPage(),
// ),
// ),
onTap: () => Navigator.push<void>(
context,
MaterialPageRoute<void>(
builder: (context) => JobDetailPage(),
),
),
),
const ListTile(
title: Text('チャットルーム一覧ページ(StreamProvider、未既読管理)'),
Expand Down
Loading