0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FlutterとGraphQLを使ったチケットアプリの作成

Posted at

はじめに

このチュートリアルでは、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コード生成
  • イベント検索機能
  • お気に入りイベント登録
  • プッシュ通知

これらの機能を追加することで、より実用的なデジタルチケットアプリケーションを作成できます

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?