Fakultas Ilmu Komputer UI

program_page.dart 8.58 KB
Newer Older
1
import 'package:flutter/cupertino.dart';
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:home_industry/Component/custom_circular.dart';
import 'package:home_industry/Component/date_time_formatter.dart';
import 'package:home_industry/Component/product_image.dart';
import 'package:home_industry/Component/router.dart';
import 'package:home_industry/Pages/Program/bloc_program/bloc.dart';
import 'package:home_industry/Pages/Program/bloc_program/program_bloc.dart';
import 'package:home_industry/Pages/Program/bloc_search_program/bloc.dart';
import 'package:home_industry/Pages/Program/model/program.dart';
import 'package:home_industry/Pages/Program/program_search_delegate.dart';
import 'package:home_industry/Pages/Program/repositories/program_repository.dart';
import 'package:home_industry/State/Auth/repositories/depedencies_repositories.dart';

class Programs extends StatelessWidget {
  const Programs({Key key}) : super(key: key);

  Future<void> onSearchPressed(BuildContext context) async {
    final searchProgram =
        SearchProgramBloc(RepositoryProvider.of<ProgramRepository>(context));
    await showSearch(
        context: context, delegate: ProgramSearchDelegate(searchProgram));
    await searchProgram.close();
  }

  @override
  Widget build(BuildContext context) {
    return RepositoryProvider<ProgramRepository>(
      create: (context) => ProgramRepository(
          dio: RepositoryProvider.of<DependenciesRepositories>(context).dio),
      child: Builder(
        builder: (BuildContext context) {
          return Scaffold(
            appBar: AppBar(
              title: Text(
Michael Wiryadinata Halim's avatar
Michael Wiryadinata Halim committed
39
                'Program',
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
                style: TextStyle(color: Colors.black),
              ),
              centerTitle: true,
              backgroundColor: Colors.white,
              elevation: 0.5,
              actions: <Widget>[
                IconButton(
                    icon: const Icon(Icons.search),
                    onPressed: () async {
                      await onSearchPressed(context);
                    })
              ],
            ),
            body: BlocProvider(
              create: (context) => ProgramBloc(
                  programRepository:
                      RepositoryProvider.of<ProgramRepository>(context))
                ..add(const FetchProgram()),
              child: const _ListProgram(),
            ),
          );
        },
      ),
    );
  }
}

class _ListProgram extends StatefulWidget {
  const _ListProgram({Key key}) : super(key: key);
  @override
  __ListProgramState createState() => __ListProgramState();
}

class __ListProgramState extends State<_ListProgram> {
  ScrollController _scrollController;
  static const _scrollThreshold = 300;

  void onScroll() {
    final maxScroll = _scrollController.position.maxScrollExtent;
    final currentScroll = _scrollController.position.pixels;
    if (maxScroll - currentScroll <= _scrollThreshold) {
      BlocProvider.of<ProgramBloc>(context).add(const FetchProgram());
    }
  }

  @override
  void initState() {
    _scrollController = ScrollController()..addListener(onScroll);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<ProgramBloc, ProgramState>(
        builder: (BuildContext context, ProgramState state) {
      if (state is InitialListProgramState) {
        return const Center(
          child: CustomCircularIndicator(),
        );
      } else if (state is ListProgramsError) {
        return Center(
          child: Text(state.error),
        );
      } else if (state is ListProgramsLoaded) {
        if (state.programs.isEmpty) {
          return const Center(
            child: Text(
Michael Wiryadinata Halim's avatar
Michael Wiryadinata Halim committed
107
              'Maaf program sementara kosong',
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
              style: TextStyle(fontSize: 20),
            ),
          );
        } else {
          return SizedBox(
            height: MediaQuery.of(context).size.height - 50,
            child: ListView.builder(
                itemCount: state.hasReachedMax
                    ? state.programs.length
                    : state.programs.length + 1,
                controller: _scrollController,
                padding: const EdgeInsets.symmetric(horizontal: 10),
                physics: const BouncingScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (BuildContext context, int index) {
                  return index >= state.programs.length
                      ? const Center(
                          child: CustomCircularIndicator(),
                        )
                      : ProgramCard(
                          program: state.programs[index],
                        );
                }),
          );
        }
      }
      return null;
    });
  }
}

class ProgramCard extends StatelessWidget {
  final Program program;
  const ProgramCard({Key key, @required this.program})
      : assert(program != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
148
      height: 230,
149
150
151
      child: Card(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(15),
152
          side: BorderSide(color: Theme.of(context).primaryColor, width: 1.5),
153
154
        ),
        child: Column(
155
            crossAxisAlignment: CrossAxisAlignment.center,
156
            children: <Widget>[
157
158
              Expanded(
                flex: 4,
159
160
161
                child: Hero(
                  tag: program.id,
                  child: CachedImage(
162
                    url: program.posterImage,
163
164
165
                  ),
                ),
              ),
166
167
168
169
170
              Flexible(
                  flex: 3,
                  child: _ProgramDescription(
                    program: program,
                  ))
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
            ]),
      ),
    );
  }
}

class _ProgramDescription extends StatelessWidget {
  final Program program;
  const _ProgramDescription({Key key, @required this.program})
      : assert(program != null),
        super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
186
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
187
188
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
189
          mainAxisAlignment: MainAxisAlignment.spaceAround,
190
191
192
193
194
          children: <Widget>[
            Text(
              program.name,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
195
              style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
196
197
198
199
200
            ),
            Row(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
201
202
203
204
205
206
                  Expanded(
                    flex: 2,
                    child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Text(
207
208
                            '${formatDate(program.startDateTime)} - '
                            '${formatDate(program.endDateTime)}',
209
210
211
212
                            overflow: TextOverflow.ellipsis,
                            style: const TextStyle(
                              fontSize: 16,
                            ),
213
                          ),
214
                          Text(
215
216
                            '${formatTime(program.startDateTime)} - '
                            '${formatTime(program.endDateTime)}',
217
218
219
220
                            overflow: TextOverflow.ellipsis,
                            style: const TextStyle(
                              fontSize: 16,
                            ),
221
                          ),
222
223
224
225
226
227
                        ]),
                  ),
                  Expanded(
                    child: _DonasiButton(
                      program: program,
                    ),
228
229
230
231
                  )
                ])
          ],
        ));
232
233
234
235
236
237
238
239
240
241
242
243
244
  }
}

class _DonasiButton extends StatelessWidget {
  final Program program;

  const _DonasiButton({
    Key key,
    @required this.program,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
245
246
247
248
249
250
251
252
    return SizedBox(
      width: 100,
      height: 40,
      child: OutlineButton(
        onPressed: () {
          Navigator.of(context).pushNamed(Router.detailProgramPage,
              arguments: {'program': program});
        },
Michael Wiryadinata Halim's avatar
Michael Wiryadinata Halim committed
253
        child: const Text('DONASI'),
254
255
256
        textColor: Theme.of(context).primaryColor,
        borderSide: BorderSide(color: Theme.of(context).primaryColor, width: 2),
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
257
258
259
260
      ),
    );
  }
}