0

Iam using Qwik.JS and GraphQL with prisma and i want to make a pop-up ( component) appear whenever my graphQL mutation in trigered :

import { $, type Signal, component$, useSignal, useStore, useTask$ } from "@builder.io/qwik";
import { server$ } from "@builder.io/qwik-city";

import { GraphQLClient } from "graphql-request";
import { Toaster } from "./Toaster";

type ContactCategory = {
  id: string;
  name: string;
};

type CounterStore = {
  count: number;
  showToaster: { value: boolean };
  categories: ContactCategory[];
  categoryId: Signal<string>;
  companyName: Signal<string>;
  lastName: Signal<string>;
  firstName: Signal<string>;
  email: Signal<string>;
  phone: Signal<string>;
  message: Signal<string>;
};

const API_URL = "https://api-inolib.vercel.app/api";

export const registerRequestQrl = server$(async (store: CounterStore) => {
  const client = new GraphQLClient(API_URL, { fetch });

  try {
    const result: { newContactRequest: { id: string } } = await client.request(
      /* GraphQL */ `
        mutation NewContactRequest(
          $categoryId: String!
          $companyName: String!
          $firstName: String!
          $lastName: String!
          $email: String!
          $phone: String!
          $message: String!
        ) {
          newContactRequest(
            categoryId: $categoryId
            companyName: $companyName
            firstName: $firstName
            lastName: $lastName
            email: $email
            phone: $phone
            message: $message
          ) {
            id
          }
        }
      `,
      {
        categoryId: store.categoryId.value,
        companyName: store.companyName.value,
        firstName: store.firstName.value,
        lastName: store.lastName.value,
        email: store.email.value,
        phone: store.phone.value,
        message: store.message.value,
      }
    );

    store.showToaster.value = true;
    console.log("result:", result);
    console.log("after:", store.showToaster.value);
  } catch (error) {
    console.error(error);
  }
});

export const ContactForm = component$(() => {
  const _categoryId = useSignal<string>("");
  const _companyName = useSignal<string>("");
  const _email = useSignal<string>("");
  const _firstName = useSignal<string>("");
  const _lastName = useSignal<string>("");
  const _message = useSignal<string>("");
  const _phone = useSignal<string>("");

  const store = useStore<CounterStore>(
    {
      count: 0,
      showToaster: { value: false },
      categories: [],
      categoryId: _categoryId,
      companyName: _companyName,
      email: _email,
      firstName: _firstName,
      lastName: _lastName,
      message: _message,
      phone: _phone,
    },
    { deep: true }
  );

  const counter$ = $((event: Event) => {
    store.count = (event.target as HTMLTextAreaElement).value.length;
  });

  console.log("before:", store.showToaster.value);

  const resetCounter$ = $(() => {
    store.count = 0;
  });

  useTask$(async () => {
    const client = new GraphQLClient(API_URL, { fetch });

    const result = await client.request<{ contactCategories: ContactCategory[] }>(/* GraphQL */ `
      query GetContactCategories {
        contactCategories {
          id
          name
        }
      }
    `);

    store.categories = result.contactCategories;
  });

  return (
    <form class="grid-rows-10 mx-[3rem] grid grid-cols-4 py-14 md:w-2/3 md:grid-rows-8 md:px-10">
      <div>{store.showToaster.value && <Toaster store={store} />}</div>

As you can see here iam passing the showToaster state into the child component :

import { component$ } from "@builder.io/qwik";

interface ToasterProps {
  store: {
    showToaster: {
      value: boolean;
    };
  };
}

export const Toaster = component$<ToasterProps>(({ store }) => {
  console.log("toasterState:", store.showToaster.value);

  return (
    <div
      id="toast-success"
      class="flex items-center w-[15rem] max-w-xs p-4 mb-4 text-gray-500 bg-white rounded-lg shadow dark:text-gray-400 dark:bg-gray-800"
      role="alert"
    >
      <div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
        <svg
          aria-hidden="true"
          class="w-5 h-5"
          fill="currentColor"
          viewBox="0 0 20 20"
          xmlns="http://www.w3.org/2000/svg"
        >
          <path
            fill-rule="evenodd"
            d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
            clip-rule="evenodd"
          ></path>
        </svg>
        <span class="sr-only">Check icon</span>
      </div>
      <div class="ml-3 text-sm font-normal">Formulaire envoyé !</div>
      <button
        onClick$={() => (store.showToaster.value = false)}
        type="button"
        class="ml-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700"
        aria-label="Close"
      >

I was expecting the Toaster component to appear after the mutation, but it's not working despite my request being sent. I tried to pass my boolean state by reference by encapsulating it into an object, but it's not working even if the state is currently changing in my console.

before: false
result: { newContactRequest: { id: 'clgote50h0003ms08mhvtvi7t' } }
after: true

I feel like iam missing something, any idea ?

Dindonix
  • 1
  • 2

0 Answers0