카테고리 없음

키오스크 앱 업그레이드 ver3

신승호. 2023. 2. 21. 15:38

기존의 키오스크앱을 활용하여 다음의 결과물을 제작할 수 있도록 합니다.

  • 음식리스트는 다음의 API 주소에서 가져올 수 있습니다.
  • 음식을 클릭하면, 주문리스트에 저장함과 동시에 앱 데이터에도 저장될 수 있도록 합니다.
  • 주문 리스트의 Chip 의 삭제버튼을 누르면 앱 데이터에도 새로 저장될 수 있도록 합니다.
  • 이 때, 앱 데이터를 저장하는 패키지는 shared_preferences 를 사용하여 해결합니다.
  • 해당과제는 새로고침을 해도 주문리스트가 남아있는지가 핵심입니다.

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^1.0.2
  shared_preferences: ^2.0.17
  dio: ^5.0.0

MainPage.dart

import 'package:assigment20/adminpage.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:dio/dio.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  List<String> order = [];
  var dio = Dio();
  var url = 'http://52.79.115.43:8090/api/collections/options/records';
  SharedPreferences? prefs;      객체

  Future getData() async {
    var res = await dio.get(url);
    return res.data["items"];
  }

  @override
  void initState() {            //한번만 실행되는 초기화함수
    super.initState();
    initPreferences(); 
  }

  void initPreferences() async {          //저장하는 함수
    prefs = await SharedPreferences.getInstance();       //initState에 의해 prefs에 새로운값이 들어감
    if (prefs != null) {
      order = prefs!.getStringList('order') ?? [];
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: GestureDetector(
          onDoubleTap: () {
            Navigator.push(context,
                MaterialPageRoute(builder: ((context) => AdminPage())));
          },
          child: Text('분식왕 이테디 주문하기'),
        ),
        centerTitle: true,
        backgroundColor: Colors.transparent,
        foregroundColor: Colors.black,
        elevation: 0,
      ),
      body: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
        Text(
          '주문 리스트',
          style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
        ),
        order.isEmpty
            ? Center(child: (Text('주문한 메뉴가 없습니다.')))
            : Wrap(
                spacing: 3,
                runSpacing: 3,
                children: order
                    .map((e) => Chip(
                        label: Text(e),
                        onDeleted: () {
                          setState(() {
                            order.remove(e);
                          });
                        }))
                    .toList()),
        Padding(
          padding: const EdgeInsets.only(top: 8),
          child: Text(
            '음식',
            style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
          ),
        ),
        Expanded(
          child: FutureBuilder(
            future: getData(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return GridView.builder(
                  itemCount: snapshot.data!.length,
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 3),
                  itemBuilder: (context, index) {
                    return GestureDetector(
                      onTap: () {
                        order.add(snapshot.data[index]['menu']);
                        if (prefs != null) {
                          prefs!.setStringList('order', order);
                        }
                        setState(() {});
                      },
                      child: Card(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Expanded(
                                child: Image(
                              image: NetworkImage(
                                  snapshot.data[index]['imageUrl']),
                              width: MediaQuery.of(context).size.width,
                              fit: BoxFit.cover,
                            )),
                            Text(snapshot.data[index]["menu"]),
                            Text(
                              '[담기]',
                              style: TextStyle(color: Colors.black),
                            ),
                          ],
                        ),
                      ),
                    );
                  },
                );
              }
              return CircularProgressIndicator();
            },
          ),
        ),
      ]),
      floatingActionButton: AnimatedOpacity(
        opacity: order.isNotEmpty ? 1 : 0,
        duration: Duration(seconds: 1),
        child: FloatingActionButton.extended(
          onPressed: () {},
          label: Text('결제하기'),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
    );
  }
}

 

메뉴를 추가하고 새로고침하면 마지막에 추가한 메뉴는 없어지길래 팀원인 관우님께 물어봐서 해결했습니다.

return GestureDetector(
                      onTap: () {
                        order.add(snapshot.data[index]['menu']);
                        if (prefs != null) {
                          prefs!.setStringList('order', order);
                        }
                        setState(() {});
                      },

첨엔 오더와 저장부분 순서를 별 생각없이 바꿔서 코드를 써서 안됐는데

관우님 말로는 마지막 메뉴를 order에 넣고 로컬에 저장해야하는데 로컬에 저장하고 order에 넣으니까 마지막 메뉴는 저장 안되고 order에만 들어간다고 말해주셨습니다. 다음에도 도움이 필요하면 관우님께...ㅎ

 

ver2에서 쓴 AdminPage는 그대로..

import 'package:flutter/material.dart';

class AdminPage extends StatelessWidget {
  const AdminPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text('Admin Page'),
          leading: GestureDetector(
              onTap: () {
                Navigator.pop(context);
              },
              child: Icon(Icons.arrow_back_ios_new)),
        ),
        body: SafeArea(
            child: Column(
          children: [
            Padding(
              padding: const EdgeInsets.all(16),
              child: Text('메뉴 추가'),
            ),
            Padding(
              padding: const EdgeInsets.all(16),
              child: Text('메뉴 삭제'),
            ),
            Padding(
              padding: const EdgeInsets.all(16),
              child: Text('메뉴 수정'),
            ),
          ],
        )),
      ),
    );
  }
}

Android Emulator - Pixel_6_Pro_API_27_5554 2023-02-21 15-35-30.mp4
8.56MB