Here you will find many of the trickier custom code used in the project. Watch this space as I will add more custom code and functions in time.

Function to remove duplicate shopping cart entries.

import 'dart:convert';
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timeago/timeago.dart' as timeago;
import '/flutter_flow/custom_functions.dart';
import '/flutter_flow/lat_lng.dart';
import '/flutter_flow/place.dart';
import '/flutter_flow/uploaded_file.dart';
import '/backend/backend.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '/backend/schema/structs/index.dart';
import '/auth/firebase_auth/auth_util.dart';

int findFirstMatchingNameIndex(List<dynamic> items) {
  /// MODIFY CODE ONLY BELOW THIS LINE

  // Accept an argument of a list of Jason items (items). One of the fields in the Json list is called name .Retrieve the last item in the list and from it the name of the item. Look through the items in the list above it and determine if there is a duplicate item by name in the list, and if there is, return the index, and if there isn't return -1.
  if (items.isEmpty) return -1;

  String lastItemName = items.last['name'];

  for (int i = 0; i < items.length - 1; i++) {
    if (items[i]['name'] == lastItemName) {
      return i;
    }
  }

  return -1;

  /// MODIFY CODE ONLY ABOVE THIS LINE
}

Function to filter kitchen orders

import 'dart:convert';
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timeago/timeago.dart' as timeago;
import '/flutter_flow/custom_functions.dart';
import '/flutter_flow/lat_lng.dart';
import '/flutter_flow/place.dart';
import '/flutter_flow/uploaded_file.dart';
import '/backend/backend.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '/backend/schema/structs/index.dart';
import '/auth/firebase_auth/auth_util.dart';

dynamic filterKitchenItems(List<OrdersRecord> allOrders) {
  /// MODIFY CODE ONLY BELOW THIS LINE

  // Accepts a list of documents references "orders", a subcollection of users. Iterate thru the document references - create a list of documents.  Within the list of documents for orders there is a list field "orderList. This is a datatype that includes the field productTypeIndex. Iterate thru the orderList of each order document, return all the items in the  orderList where a productTypeIndex equal to 2 in json format. An orderList can have more than 1 item in its list.
  List<dynamic> filteredItems = [];

  for (var order in allOrders) {
    if (order.orderList != null) {
      for (var item in order.orderList) {
        if (item.productTypeIndex == 2) {
          filteredItems.add(item);
        }
      }
    }
  }

  return jsonEncode(filteredItems);

  /// MODIFY CODE ONLY ABOVE THIS LINE
}

Function to change unix timestamp to "seconds ago".

import 'dart:convert';
import 'dart:math' as math;

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
import 'package:timeago/timeago.dart' as timeago;
import '/flutter_flow/custom_functions.dart';
import '/flutter_flow/lat_lng.dart';
import '/flutter_flow/place.dart';
import '/flutter_flow/uploaded_file.dart';
import '/backend/backend.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import '/backend/schema/structs/index.dart';
import '/auth/firebase_auth/auth_util.dart';

String? secondsToTimeAgo(DateTime unixSeconds) {
  /// MODIFY CODE ONLY BELOW THIS LINE

  //  Convert unix time Firebase in seconds to text "x minutes ago"
  final difference = DateTime.now().difference(unixSeconds);
  return timeago.format(DateTime.now().subtract(difference));

  /// MODIFY CODE ONLY ABOVE THIS LINE
}

Get filtered Kitchen Items

const functions = require('firebase-functions');
const admin = require('firebase-admin');
// To avoid deployment errors, do not call admin.initializeApp() in your code

exports.getFilteredOrderItems = functions.
	runWith({
		memory: '256MB'
  }).https.onCall(
  async (data, context) => {
		const userId = data.userId;
    // Write your code below!
  if (!userId) {
    throw new functions.https.HttpsError("invalid-argument", "User ID is required.");
  }

  const ordersSnapshot = await admin.firestore()
    .collection("users")
    .doc(userId)
    .collection("orders")
    .get();

  let filteredItems = [];

  ordersSnapshot.forEach(orderDoc => {
    const orderData = orderDoc.data();
    const orderList = orderData.orderList || [];
    orderList.forEach(item => {
      if (item.productTypeIndex === 2) {
        filteredItems.push(item);
      }
    });
  });

  return filteredItems; // Returns as a JSON lis
    // Write your code above!
  }
);

Update Ready Line Item Status On

const functions = require('firebase-functions');
const admin = require('firebase-admin');
// To avoid deployment errors, do not call admin.initializeApp() in your code

exports.updateReadyLineItemStatus = functions.https.onCall(
  async (data, context) => {
try {
      const userId = data.userId;
      const orderId = data.orderId;
      const itemIndex = data.itemIndex;

      if (!userId || !orderId || itemIndex === undefined) {
        throw new functions.https.HttpsError(
          'invalid-argument',
          'Missing userId, orderId, or itemIndex.'
        );
      }
    // Write your code below!
    // Reference to the order document
    const orderDocRef =  await admin.firestore()
      .collection('users')
      .doc(userId)
      .collection('orders')
      .doc(orderId);

    // Read the document
    const orderDoc = await orderDocRef.get();

    if (!orderDoc.exists) {
    throw new functions.https.HttpsError('not-found', 'Order document not found.');
    }

    const orderData = orderDoc.data();

    if (!Array.isArray(orderData.orderList)) {
      throw new functions.https.HttpsError('failed-precondition', 'orderList is not an array.');
    }

    if (itemIndex < 0 || itemIndex >= orderData.orderList.length) {
      throw new functions.https.HttpsError('out-of-range', 'itemIndex out of bounds.');
    }

    // Update the readyLineItemStatus field in the specified item
    const updatedOrderList = [...orderData.orderList];
    updatedOrderList[itemIndex] = {
      ...updatedOrderList[itemIndex],
      readyLineItemStatus: true,
    };

    // Write back the updated array
    await orderDocRef.update({ orderList: updatedOrderList });

    return { message: 'readyLineItemStatus updated successfully.' };
  } catch (error) {
      console.error('Error updating readyLineItemStatus:', error);
      if (error instanceof functions.https.HttpsError) {
        throw error; // Re-throw known errors
      }
      throw new functions.https.HttpsError(
        'internal',
        'Internal server error'
      );
    }
    // Write your code above!
  }
);

Update Ready Line Item Status Off

const functions = require('firebase-functions');
const admin = require('firebase-admin');
// To avoid deployment errors, do not call admin.initializeApp() in your code

exports.updateReadyLineItemStatusFalse = functions.https.onCall(
  async (data, context) => {
try {
      const userId = data.userId;
      const orderId = data.orderId;
      const itemIndex = data.itemIndex;

      if (!userId || !orderId || itemIndex === undefined) {
        throw new functions.https.HttpsError(
          'invalid-argument',
          'Missing userId, orderId, or itemIndex.'
        );
      }
    // Write your code below!
    // Reference to the order document
    const orderDocRef =  await admin.firestore()
      .collection('users')
      .doc(userId)
      .collection('orders')
      .doc(orderId);

    // Read the document
    const orderDoc = await orderDocRef.get();

    if (!orderDoc.exists) {
    throw new functions.https.HttpsError('not-found', 'Order document not found.');
    }

    const orderData = orderDoc.data();

    if (!Array.isArray(orderData.orderList)) {
      throw new functions.https.HttpsError('failed-precondition', 'orderList is not an array.');
    }

    if (itemIndex < 0 || itemIndex >= orderData.orderList.length) {
      throw new functions.https.HttpsError('out-of-range', 'itemIndex out of bounds.');
    }

    // Update the readyLineItemStatus field in the specified item
    const updatedOrderList = [...orderData.orderList];
    updatedOrderList[itemIndex] = {
      ...updatedOrderList[itemIndex],
      readyLineItemStatus: false,
    };

    // Write back the updated array
    await orderDocRef.update({ orderList: updatedOrderList });

    return { message: 'readyLineItemStatus updated successfully.' };
  } catch (error) {
      console.error('Error updating readyLineItemStatus:', error);
      if (error instanceof functions.https.HttpsError) {
        throw error; // Re-throw known errors
      }
      throw new functions.https.HttpsError(
        'internal',
        'Internal server error'
      );
    }
    // Write your code above!
  }
);