Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб7.docx
Скачиваний:
0
Добавлен:
02.08.2026
Размер:
140 Кб
Скачать

Министерство цифрового развития, связи и массовых коммуникаций РФ

ордена Трудового Красного Знамени федеральное государственное

бюджетное образовательное учреждение высшего образования

«МОСКОВСКИЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ СВЯЗИ И

ИНФОРМАТИКИ»

Кафедра «МКиИТ»

Лабораторная № 7

по дисциплине «Разработка кроссплатформенного программного обеспечения»

Реализация CRUD-запросов

Выполнил:

студент группы БФИ2203

Михайлов К. А.

Проверил:

Потапченко Т.Д.

Москва, 2024 г.

Цель работы:

В рамках этой лабораторной работы вам нужно будет модифицировать функционал корзины товаров, реализованного в лабораторной работе №6. Также научимся работать с GitHub Pages.

Требования к работе:

  1. Работа с внешним API заказов(например, https://jsonplaceholder.typicode.com, https://dummyjson.com или любое другое подходящее). API должно поддерживать операции:

  • POST-запрос — для отправки заказа на сервер и получения его номера.

  • GET-запрос — для получения истории заказов и отображения их в приложении.

  • DELETE-запрос — для удаления заказа из истории.

  1. Страница оформления заказа:

  • Интеграция с картой для указания места доставки (использовать библиотеку react-yandex-maps для отображения карты, на которой пользователь может указать место доставки)

  • При оформлении заказа необходимо добавить поле для выбора даты доставки.

  1. Хранение истории заказов:

  • История заказов будет отображаться в приложении на отдельной странице, и при необходимости можно будет удалить заказ.

  1. Интеграция с AsyncStorage:

  • Несмотря на работу с API, состояние корзины должно сохраняться в AsyncStorage, чтобы при перезагрузке приложения данные сохранялись.

  1. Интерфейс пользователя:

  • Интуитивно понятный интерфейс с возможностью оформления заказов, отображения истории заказов и удаления заказа.

  • Вывод всех необходимых данных (стоимость, номер заказа, место доставки, дата доставки).

Листинг кода

import React from 'react';

import { useEffect, useState } from 'react';

import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';

import { NavigationContainer } from '@react-navigation/native';

import { createStackNavigator } from '@react-navigation/stack';

import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

import Footer from './components/Footer';

import MainScreen from './screens/MainScreen';

import AsyncStorage from '@react-native-async-storage/async-storage';

import axios from 'axios';

import MakeOrderScreen from './screens/MakeOrderScreen';

import OrdersHistoryScreen from './screens/OrdersHistoryScreen';

import OrderDetailsScreen from './screens/OrderDetailsScreen';

const Stack = createStackNavigator();

export default function App() {

  const [data, setData] = useState([])

  const [deferred, setDeferred] = useState([

    // { key: '9', price: 101, quantity: 1, text: 'Товар A' },

    // { key: '10', price: 102, quantity: 1, text: 'Товар B' },

  ]);

  const [totalSum, setTotalSum] = useState(0);

  const [orders, setOrders] = useState([

  ]);

 

  useEffect(() => {

    const loadData = async () => {

        try {

            const storedData = await AsyncStorage.getItem('inCart');

            const storedDeferred = await AsyncStorage.getItem('deferred');

            const storedOrders = await AsyncStorage.getItem('orders');

            if (storedData) setData(JSON.parse(storedData));

            else {

                response = await axios.get('https://my-json-server.typicode.com/stproger/myFakeJSON/inCart');

                setData(response.data);

            }

            if (storedDeferred) setDeferred(JSON.parse(storedDeferred));

            else {

                response = await axios.get('https://my-json-server.typicode.com/stproger/myFakeJSON/deffered');

                setDeferred(response.data);

            }

            if (storedOrders) setOrders(JSON.parse(storedOrders));

            else {

                response = await axios.get('https://my-json-server.typicode.com/stproger/myFakeJSON/orders');

                setOrders(response.data);

            }

        } catch (e) {

            console.error('Ошибка загрузки данных:', e);

        }

    };

    loadData();

}, []);

useEffect(() => {

    const saveData = async () => {

        try {

            await AsyncStorage.setItem('inCart', JSON.stringify(data));

            await AsyncStorage.setItem('deferred', JSON.stringify(deferred));

            await AsyncStorage.setItem('orders', JSON.stringify(orders));

        } catch (e) {

            console.error('Ошибка сохранения данных:', e);

        }

        try {

            console.log('Отправка данных')

            const cart_response = await axios.post('https://jsonplaceholder.typicode.com/users/1/posts', data);

            const deferred_response = await axios.post('https://jsonplaceholder.typicode.com/users/1/posts', deferred);

            const orders_response = await axios.post('https://jsonplaceholder.typicode.com/users/1/posts', orders);

        } catch (e) {

            console.error('Ошибка отправки данных:', e);

        }

    };

    saveData();

}, [data, deferred]);

  return (

    <NavigationContainer>

      <View style={styles.body}>

      <Stack.Navigator>

        <Stack.Screen

          name="MainScreen"

          children={() => (

            <MainScreen

              data={data}

              deferred={deferred}

              totalSum={totalSum}

              setData={setData}

              setDeferred={setDeferred}

              setTotalSum={setTotalSum}

            />

          )}

          options={{ headerShown: false }}

        />

        <Stack.Screen

          name="MakeOrderScreen"

          children={() => (

            <MakeOrderScreen data={data} setData={setData} totalSum={totalSum} setOrders={setOrders} orders={orders} />

          )}

          options={{ headerTitle: "Вернуться к корзине"}}/>

        <Stack.Screen name="OrdersHistoryScreen"

          children={() => (

            <OrdersHistoryScreen orders={orders} />

            )}

          options={{ headerTitle: "Вернуться к корзине"}}/>

        <Stack.Screen name="OrderDetailsScreen" component={OrderDetailsScreen} options={{ title: 'Детали заказа' }} />

      </Stack.Navigator>

      </View>

    </NavigationContainer>

  );

}

const styles = StyleSheet.create({

  body: {

    flex: 1,

    flexDirection: 'column',

    borderLeftWidth: 4,

    borderRightWidth: 4,

    borderColor: "#ddd",

    marginHorizontal: "auto",

    maxWidth: 1000,

    width: '100%',

  },

  header: {

    fontSize: "2em",

    textAlign: 'center',

    marginVertical: 10,

  }

});

import React from 'react';

import { useEffect, useState } from 'react';

import { View, Text, StyleSheet, Button, TouchableOpacity } from 'react-native';

import { useNavigation } from '@react-navigation/native';

import { NavigationContainer } from '@react-navigation/native';

import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

import Footer from '../components/Footer';

import CartTab from "../tabs/CartTab";

import AddProductTab from "../tabs/AddProductTab";

import DeferredTab from "../tabs/DeferredTab";

import AsyncStorage from '@react-native-async-storage/async-storage';

import axios from 'axios';

import { ScrollView } from 'react-native-web';

const Tab = createMaterialTopTabNavigator();

export default function MainScreen({data, deferred, totalSum, setData, setDeferred, setTotalSum}) {

    const navigation = useNavigation();

    const addProduct = (product) => {

        setData(prevItems => [...prevItems, product]);

    };

    useEffect(() => {

        const total = data.reduce((sum, item) => sum + item.price * item.quantity, 0)

        setTotalSum(total)

    }, [data])

    const updateQuantity = (key, quantity, type) => {

        if (type === "data") {

            setData(prevItems =>

                prevItems.map(item =>

                    item.key === key ? { ...item, quantity } : item

                )

            );

        } else if (type === "deferred") {

            setDeferred(prevItems =>

                prevItems.map(item =>

                    item.key === key ? { ...item, quantity } : item

                )

            );

        }

    };

    const deleteItem = (key, type) => {

        if (type === "data") {

            setData(prevItems =>

                prevItems.filter(item => item.key !== key)

            );

        } else if (type === "deferred") {

            setDeferred(prevItems =>

                prevItems.filter(item => item.key !== key)

            );

        }

    };

    const switchItem = (key, type) => {

        const moveProduct = (source, destination, setSource, setDestination) => {

            const product = source.find(item => item.key === key);

            if (product) {

                setDestination(prevItems => [...prevItems, product]);

                setSource(prevData => prevData.filter(item => item.key !== key));

            }

        };

        if (type === "data") {

            moveProduct(data, deferred, setData, setDeferred);

        } else if (type === "deferred") {

            moveProduct(deferred, data, setDeferred, setData);

        }

    };

    const clearCart = () => {

        setData([]);

    }

    return (

        <View style={styles.container}>

        <TouchableOpacity style={styles.historyButton} onPress={() => navigation.navigate("OrdersHistoryScreen")}>

            <Text style={styles.historyButtonText}>{"<- К истории заказов"}</Text>

        </TouchableOpacity>

        <Text style={styles.header}>Корзина</Text>

        <Tab.Navigator

            screenOptions={{

                tabBarActiveTintColor: 'blue',

                tabBarLabelStyle: { fontSize: 14, fontWeight: 'bold' },

                tabBarStyle: { backgroundColor: 'white' },

            }}

        >

            <Tab.Screen name="Товары к покупке" children={() => (

                <ScrollView style={styles.body}>

                <CartTab data={data} updateQuantity={updateQuantity} deleteItem={deleteItem} setDeferred={setDeferred} switchItem={switchItem} />

                </ScrollView>

                )} />

            <Tab.Screen name="Отложенные товары" children={() => (

                <ScrollView style={styles.body}>

                <DeferredTab data={deferred} setData={setData} updateQuantity={updateQuantity} deleteItem={deleteItem} switchItem={switchItem} />

                </ScrollView>

                )} />

            <Tab.Screen name="Добавить товар" children={() => (

                <ScrollView style={styles.body}>

                <AddProductTab addProduct={addProduct} />

                </ScrollView>

                )} />

        </Tab.Navigator>

        <Footer totalSum={totalSum} clearCart={clearCart} ></Footer>

        </View>

    );

}

const styles = StyleSheet.create({

    container: {

        backgroundColor: "white",

        height: "100%"

    },

    body: {

        flex: 1,

        flexDirection: 'column',

        marginHorizontal: "auto",

        width: '100%',

        maxHeight: "100%",

    },

    header: {

      fontSize: "2em",

      textAlign: 'center',

      marginVertical: 10,

    },

    historyButton: {

        paddingHorizontal: 15

    },

    historyButtonText: {

        fontSize: "1.5em",

        color: "gray",

        textDecorationLine: "underline",

    },

  });

Import React from 'react';

Import { useEffect, useState } from 'react';

import { View, Text, TextInput, Button, StyleSheet, ScrollView } from 'react-native';

import { useNavigation } from '@react-navigation/native';

import { YMaps, Map, Placemark } from '@pbe/react-yandex-maps';

export default function MakeOrderScreen({ data, setData, totalSum, setOrders, orders }) {

    const navigation = useNavigation();

    const [deliveryDate, setDeliveryDate] = useState("");

    const [deliveryAddress, setDeliveryAddress] = useState([55.751244, 37.618423]);

    const addOrder = () => {

        const newOrder = {

            key: `${Date.now()}`, // Генерация уникального key с использованием текущего времени

            date: deliveryDate,

            address: deliveryAddress.join(", "),

            products: [...data],

            totalSum: totalSum,

        }

        setOrders(prevItems => [...prevItems, newOrder]);

        setData([]);

        setDeliveryDate('');

        setDeliveryAddress('');

    }

    const defaultState = {

        center: deliveryAddress,

        zoom: 10,

      };

    const handleMapClick = (event) => {

        const coords = event.get('coords');

        setDeliveryAddress(coords);

      };

    return (

        <ScrollView style={styles.container}>

            <Text style={styles.header}>Оформление заказа</Text>

            {/* Данные о товарах */}

            <View style={styles.orderDetails}>

                {data.map(item => (

                    <View key={item.key} style={styles.item}>

                        <Text style={styles.itemText}>{item.text}</Text>

                        <Text>{`Цена: ${item.price} ₽`}</Text>

                        <Text>{`Количество: ${item.quantity}`}</Text>

                    </View>

                ))}

            </View>

            {/* Сумма заказа */}

            <Text style={styles.totalSum}>Итого: {totalSum} ₽</Text>

            {/* Выбор даты доставки */}

            <Text>Выберите дату доставки:</Text>

            <input

                type="date"

                value={deliveryDate}

                onChange={(e) => setDeliveryDate(e.target.value)}

                style={{ padding: 10, fontSize: 16, marginBottom: 10 }}

            />

            {/* Ввод адреса доставки */}

            <Text>Введите адрес доставки:</Text>

            <div style={styles.webMap}>

                <YMaps>

                    <Map

                        defaultState={defaultState}

                        width="100%"

                        height="400px"

                        onClick={handleMapClick}

                    >

                        <Placemark geometry={deliveryAddress} />

                    </Map>

                </YMaps>

            </div>

            <TextInput

                style={styles.input}

                placeholder="Улица, дом, квартира"

                value={deliveryAddress}

                onChangeText={setDeliveryAddress}

            />

            {/* Кнопка подтверждения заказа */}

            <Button

                title="Подтвердить заказ"

                onPress={() => {

                    addOrder();

                    alert(`Заказ подтвержден на адрес: ${deliveryAddress} с датой доставки: ${deliveryDate}`);

                    navigation.navigate('MainScreen');

                }}

            />

        </ScrollView>

    );

}

const styles = StyleSheet.create({

    container: {

        backgroundColor: "white",

        padding: 20,

    },

    header: {

        fontSize: 24,

        fontWeight: 'bold',

        marginBottom: 20,

    },

    orderDetails: {

        marginBottom: 20,

    },

    item: {

        marginBottom: 10,

        borderBottomWidth: 1,

    },

    itemText: {

        fontWeight: 'bold',

    },

    totalSum: {

        fontSize: 18,

        fontWeight: 'bold',

        marginBottom: 20,

    },

    input: {

        height: 40,

        borderColor: '#ccc',

        borderWidth: 1,

        marginBottom: 20,

        paddingHorizontal: 10,

    },

});

Соседние файлы в предмете Программирование на HTML/CSS/JavaScript (Веб-разработка)