You are an expert software engineer specialised in Next.js 14 with TypeScript. I will share you my code implementations. I'll need you to resolve an error that I am encountering.

---

Code implementations:

app/submissions/page.tsx

```
import Assessment from "@/database/models/assessment.model";
import Attempt from "@/database/models/attempt.model";
import SubmissionModel from "@/database/models/submission.model";
import { getSession } from "@auth0/nextjs-auth0";
import Submission, { ISubmissionProps } from "./submission";
import Container from "@/components/c-ui/container";
import connectDb from "@/database/connect";

export default async function Page() {
  const session = await getSession();
  if (!session) return null;

  await connectDb();

  const submissions = await SubmissionModel.find({ teacherId: session.user.email }, { _id: 1, title: 1 }).lean().exec();

  const allAssessments = await Assessment.find(
    { submissionId: { $in: submissions.map((el) => el._id) } },
    { _id: 1, submissionId: 1, questionId: 1 }
  )
    .lean()
    .exec();

  const allAttempts = await Attempt.find(
    { assessmentId: { $in: allAssessments.map((el) => el._id) }, questionId: { $in: allAssessments.map((el) => el.questionId) } },
    { assessmentId: 1, submittedAt: 1, markedAt: 1, verifiedAt: 1 }
  )
    .lean()
    .exec();

  const propsArray: ISubmissionProps[] = submissions.map((el) => {
    const assessments = allAssessments.filter((ele) => ele.submissionId === el._id).map((ele) => ele._id);
    const attempts = allAttempts.filter((ele) => assessments.indexOf(ele.assessmentId) !== -1);
    let submittedCount = 0;
    let markedCount = 0;
    let verifiedCount = 0;
    for (let i = 0; i < attempts.length; i++) {
      const attempt = attempts[i];
      if (!!attempt.submittedAt) submittedCount++;
      if (!!attempt.markedAt) markedCount++;
      if (!!attempt.verifiedAt) verifiedCount++;
    }

    return { id: el._id, title: el.title, submittedCount, markedCount, verifiedCount };
  });

  return (
    <div className="h-full w-full flex shrink-0 overflow-x-hidden overflow-y-auto content-start p-8 lg:p-24 gap-4 lg:gap-8">
      <Container
        childComponent={Submission}
        propsArray={propsArray}
        keyPrefix="submission"
        widthInvisible="w-full"
        childrenPerRow={{ lg: 2, "2xl": 3 }}
      />
    </div>
  );
}
```

components/c-ui/container.tsx

```
"use client";

import React, { useMemo } from "react";
import useScreenWidth from "../../hooks/screen-width.hook";

/**
 * Defines the possible TailwindCSS breakpoints.
 */
type Breakpoint = "base" | "sm" | "md" | "lg" | "xl" | "2xl";

/**
 * Props interface for the Container component.
 *
 * @template P - The type of the props expected by the child component.
 */
interface ContainerProps<P> {
  /**
   * The child component to be rendered within the container.
   */
  childComponent: React.ComponentType<P>;

  /**
   * An array of props that will be passed to each child component.
   */
  propsArray: P[];

  /**
   * A prefix string to ensure unique keys for each child component.
   */
  keyPrefix: string;

  /**
   * The invisible component to fill empty spots in a row.
   * This ensures consistent spacing by occupying space similar to child components.
   */
  widthInvisible: string;

  /**
   * An object specifying the number of children per row for each TailwindCSS breakpoint.
   * Example:
   * {
   *   base: 1,
   *   md: 2,
   *   xl: 3
   * }
   */
  childrenPerRow?: Partial<Record<Breakpoint, number>>;
}

/**
 * Container component to display child components in a responsive, wrapping layout.
 * Ensures space-between behavior for each row with customizable gaps and fills empty spaces with an invisible component.
 *
 * @template P - The type of the props expected by the child component.
 *
 * @param {ContainerProps<P>} props - The props for the Container component.
 *
 * @returns {JSX.Element} The rendered Container component.
 */
const Container = <P,>({
  childComponent: ChildComponent,
  propsArray,
  keyPrefix,
  widthInvisible,
  childrenPerRow,
}: ContainerProps<P>): JSX.Element => {
  // Determine screen size using the useScreenWidth hook for each breakpoint
  const is2xl = useScreenWidth("2xl");
  const isXl = useScreenWidth("xl");
  const isLg = useScreenWidth("lg");
  const isMd = useScreenWidth("md");
  const isSm = useScreenWidth("sm");

  /**
   * Determines the current number of children per row based on the active breakpoint.
   * It checks from the largest breakpoint to the smallest to find the highest matching breakpoint.
   */
  const numberOfChildrenPerRow = useMemo(() => {
    if (is2xl && childrenPerRow?.["2xl"]) {
      return childrenPerRow["2xl"]!;
    } else if (isXl && childrenPerRow?.["xl"]) {
      return childrenPerRow["xl"]!;
    } else if (isLg && childrenPerRow?.["lg"]) {
      return childrenPerRow["lg"]!;
    } else if (isMd && childrenPerRow?.["md"]) {
      return childrenPerRow["md"]!;
    } else if (isSm && childrenPerRow?.["sm"]) {
      return childrenPerRow["sm"]!;
    } else {
      return childrenPerRow?.["base"] ?? 1; // Default to 1 if 'base' is not specified
    }
  }, [is2xl, isXl, isLg, isMd, isSm, childrenPerRow]);

  /**
   * Groups the propsArray into chunks based on the numberOfChildrenPerRow.
   * Each chunk represents a row of child components.
   */
  const rows: P[][] = useMemo(() => {
    const tempRows: P[][] = [];
    for (let i = 0; i < propsArray.length; i += numberOfChildrenPerRow) {
      tempRows.push(propsArray.slice(i, i + numberOfChildrenPerRow));
    }
    return tempRows;
  }, [propsArray, numberOfChildrenPerRow]);

  /**
   * Generates required number of invisible components to fill the empty spots in a row.
   *
   * @param {number} missingCount - The number of invisible components needed.
   * @param {number} rowIndex - The index of the current row.
   *
   * @returns {JSX.Element[]} An array of invisible components.
   */
  const renderInvisibleComponents = (missingCount: number, rowIndex: number): JSX.Element[] => {
    return Array.from({ length: missingCount }, (_, idx) => (
      <div key={`${keyPrefix}-invisible-${rowIndex}-${idx}`} className={`invisible ${widthInvisible}`} />
    ));
  };

  return (
    <div className="h-fit w-full flex flex-col gap-8">
      {rows.map((row, rowIndex) => {
        const missingCount = numberOfChildrenPerRow - row.length;
        return (
          <div key={`${keyPrefix}-row-${rowIndex}`} className="h-fit w-full flex justify-between gap-8 lg:gap-10 xl:gap-12">
            {row.map((childProps, childIndex) => (
              <ChildComponent key={`${keyPrefix}-${rowIndex}-${childIndex}`} {...childProps} />
            ))}
            {missingCount > 0 && renderInvisibleComponents(missingCount, rowIndex)}
          </div>
        );
      })}
    </div>
  );
};

export default Container;
```

app/submissions/submission.tsx

```
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { Share1Icon } from "@radix-ui/react-icons";
import { CheckCheckIcon } from "lucide-react";
import Link from "next/link";
import React from "react";

export interface ISubmissionProps {
  id: string;
  title: string;
  verifiedCount: number;
  markedCount: number;
  submittedCount: number;
}

const Submission = ({ id, title, verifiedCount, markedCount, submittedCount }: ISubmissionProps) => {
  return (
    <Card key={`submission-${id}`} className="relative h-fit w-full opacity-60 hover:opacity-100">
      <Link href={`/submissions/${id}`} className="group">
        <CardHeader className="h-20 pb-0">
          <CardTitle className="group-hover:underline leading-6 line-clamp-2">{title}</CardTitle>
        </CardHeader>
        <CardContent className="h-fit w-full flex mb-16">
          <div className="h-10 w-full flex flex-col items-center justify-between">
            <p>{verifiedCount}</p>
            <p className="text-xs">Verified</p>
          </div>
          <Separator orientation="vertical" className="h-10" />
          <div className="h-10 w-full flex flex-col items-center justify-between">
            <p>{markedCount}</p>
            <p className="text-xs">Marked</p>
          </div>
          <Separator orientation="vertical" className="h-10" />
          <div className="h-10 w-full flex flex-col items-center justify-between">
            <p>{submittedCount}</p>
            <p className="text-xs">Submitted</p>
          </div>
        </CardContent>
      </Link>
      <CardFooter className="bottom-0 left-0 absolute h-16 w-full flex gap-4 z-10">
        <Button className="w-1/2 shrink">
          <Share1Icon className="h-5 w-5 mr-2" />
          Submit Link
        </Button>
        <Button className="w-1/2 shrink">
          <CheckCheckIcon className="h-5 w-5 mr-2" />
          Mark
        </Button>
      </CardFooter>
    </Card>
  );
};

export default Submission;
```

---

Here's the error:

```
 ⨯ Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
  <... childComponent={function Submission} propsArray=... keyPrefix=... widthInvisible=... childrenPerRow=...>
                      ^^^^^^^^^^^^^^^^^^^^^
    at stringify (<anonymous>)
digest: "860459365"
```