はじめに
このチュートリアルでは、FlutterとGraphQLを使用してデジタルチケット販売アプリを作成します。ユーザーがチケットを購入でき、イベント主催者がイベントを登録できるアプリを構築します[1][3]。
プロジェクトのセットアップ
まず、新しいFlutterプロジェクトを作成します:
flutter create digital_ticket_app
cd digital_ticket_app
次に、必要なパッケージをpubspec.yamlに追加します:
dependencies:
flutter:
sdk: flutter
graphql_flutter: ^5.1.2
intl: ^0.17.0
パッケージをインストールします:
flutter pub get
GraphQLスキーマの定義
lib/graphql/schema.graphql
ファイルを作成し、以下のスキーマを定義します:
type Event {
id: ID!
title: String!
description: String!
date: String!
price: Float!
availableTickets: Int!
}
type Ticket {
id: ID!
eventId: ID!
userId: ID!
purchaseDate: String!
}
type Query {
events: [Event!]!
myTickets(userId: ID!): [Ticket!]!
}
type Mutation {
createEvent(title: String!, description: String!, date: String!, price: Float!, availableTickets: Int!): Event!
purchaseTicket(eventId: ID!, userId: ID!): Ticket!
}
GraphQLクライアントの設定
lib/graphql/client.dart
ファイルを作成し、GraphQLクライアントを設定します:
import 'package:graphql_flutter/graphql_flutter.dart';
final HttpLink httpLink = HttpLink('YOUR_GRAPHQL_ENDPOINT');
final GraphQLClient client = GraphQLClient(
link: httpLink,
cache: GraphQLCache(),
);
ValueNotifier<GraphQLClient> clientNotifier = ValueNotifier(client);
イベント一覧画面の作成
lib/screens/event_list_screen.dart
ファイルを作成し、イベント一覧を表示する画面を実装します:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class EventListScreen extends StatelessWidget {
const EventListScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('イベント一覧')),
body: Query(
options: QueryOptions(
document: gql('''
query GetEvents {
events {
id
title
date
price
availableTickets
}
}
'''),
),
builder: (QueryResult result, {VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}
List<dynamic> events = result.data?['events'] ?? [];
return ListView.builder(
itemCount: events.length,
itemBuilder: (context, index) {
final event = events[index];
return ListTile(
title: Text(event['title']),
subtitle: Text('${event['date']} - ¥${event['price']}'),
trailing: Text('残り${event['availableTickets']}枚'),
onTap: () {
// イベント詳細画面に遷移
},
);
},
);
},
),
);
}
}
チケット購入機能の実装
lib/screens/event_detail_screen.dart
ファイルを作成し、チケット購入機能を実装します:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class EventDetailScreen extends StatelessWidget {
final String eventId;
const EventDetailScreen({Key? key, required this.eventId}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('イベント詳細')),
body: Query(
options: QueryOptions(
document: gql('''
query GetEvent(\$id: ID!) {
event(id: \$id) {
id
title
description
date
price
availableTickets
}
}
'''),
variables: {'id': eventId},
),
builder: (QueryResult result, {VoidCallback? refetch, FetchMore? fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return Center(child: CircularProgressIndicator());
}
final event = result.data?['event'];
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(event['title'], style: Theme.of(context).textTheme.headline5),
SizedBox(height: 8),
Text(event['description']),
SizedBox(height: 16),
Text('日時: ${event['date']}'),
Text('価格: ¥${event['price']}'),
Text('残りチケット: ${event['availableTickets']}枚'),
SizedBox(height: 24),
ElevatedButton(
child: Text('チケットを購入'),
onPressed: () {
// チケット購入処理
},
),
],
),
);
},
),
);
}
}
イベント作成画面の実装
lib/screens/create_event_screen.dart
ファイルを作成し、イベント作成機能を実装します:
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class CreateEventScreen extends StatefulWidget {
@override
_CreateEventScreenState createState() => _CreateEventScreenState();
}
class _CreateEventScreenState extends State<CreateEventScreen> {
final _formKey = GlobalKey<FormState>();
String _title = '';
String _description = '';
DateTime _date = DateTime.now();
double _price = 0.0;
int _availableTickets = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('イベント作成')),
body: Mutation(
options: MutationOptions(
document: gql('''
mutation CreateEvent(\$title: String!, \$description: String!, \$date: String!, \$price: Float!, \$availableTickets: Int!) {
createEvent(title: \$title, description: \$description, date: \$date, price: \$price, availableTickets: \$availableTickets) {
id
title
}
}
'''),
onCompleted: (dynamic resultData) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('イベントが作成されました')));
Navigator.pop(context);
},
),
builder: (RunMutation runMutation, QueryResult? result) {
return Form(
key: _formKey,
child: ListView(
padding: EdgeInsets.all(16.0),
children: [
TextFormField(
decoration: InputDecoration(labelText: 'タイトル'),
validator: (value) => value!.isEmpty ? 'タイトルを入力してください' : null,
onSaved: (value) => _title = value!,
),
TextFormField(
decoration: InputDecoration(labelText: '説明'),
validator: (value) => value!.isEmpty ? '説明を入力してください' : null,
onSaved: (value) => _description = value!,
),
// 日付、価格、チケット数のフィールドも追加
ElevatedButton(
child: Text('イベントを作成'),
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
runMutation({
'title': _title,
'description': _description,
'date': _date.toIso8601String(),
'price': _price,
'availableTickets': _availableTickets,
});
}
},
),
],
),
);
},
),
);
}
}
まとめ
このチュートリアルでは、FlutterとGraphQLを使用してデジタルチケット販売アプリの基本的な機能を実装しました。イベント一覧の表示、チケット購入、イベント作成などの主要機能を含んでいます[4][5]。
実際のアプリケーションでは、認証機能やエラーハンドリング、より詳細なUI/UXの実装が必要になります。また、バックエンドのGraphQLサーバーの実装も必要です。
このアプリをさらに発展させるには、以下の機能を追加することをおすすめします:
- ユーザー認証
- チケットのQRコード生成
- イベント検索機能
- お気に入りイベント登録
- プッシュ通知
これらの機能を追加することで、より実用的なデジタルチケットアプリケーションを作成できます