0

I have a problem with my application. On my page there are several components, Header.jsx, Hero.jsx, Footer etc. In Header I have implemented the search bar and it displays dynamic response, when I type it filters the results.

In the Hero component I have like a carousel of pictures. Under the carousel, there are 3 buttons (Step1, Step2, Step3). When I click on step1 it gets me the first picture, step2 the second etc.

The task I am given should make search options clickable and when I type for example "Software" in search prompt and when clicked it should get me the step1, or step2, or step3 doesn't matter. I will have 3 keywords when clicked it will be pointed to those steps, and also I will have the case for other keywords that will get me to the specific word or else on the page.

store.ts :

"use client";
// redux/store.ts
import { configureStore } from "@reduxjs/toolkit";
import ugoReducer from "./slices/ugoSlice";
import { type } from "os";

export const store = configureStore({
  reducer: {
    ugo: ugoReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;




provider.ts:
"use client";

import { Provider } from "react-redux";
import { store } from "./store";

export function Providers({ children }) {
  return <Provider store={store}>{
    children}`your text`
    </Provider>;
}

ugoSlice.ts:
"use client";
import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  activeStepIndex: 0,
  activeContent: null,
};

const ugoSlice = createSlice({
  name: "ugo",
  initialState,
  reducers: {
    setActiveStepIndex: (state, action) => {
      state.activeStepIndex = action.payload;
    },
    setActiveContent: (state, action) => {
      state.activeContent = action.payload;
    },
  },
});

export const { setActiveStepIndex, setActiveContent } = ugoSlice.actions;
export default ugoSlice.reducer;`

layout.tsx:
`
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import { Providers } from "@/redux/provider";

const inter = Inter({ subsets: ["latin"] });

export const metadata: Metadata = {
  title: "pagepage",
  description: "pagename",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Header.jsx:

"use client";
import { Fragment, useEffect, useState, useRef } from "react";
import { usePathname } from "next/navigation";
import clsx from "clsx";
import { Menu, Popover, Transition } from "@headlessui/react";
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
import { Bars3Icon, XMarkIcon } from "@heroicons/react/24/outline";
import { Logo } from "@/components/Logo";
import { useDispatch } from "react-redux";
import { setActiveStepIndex, setActiveContent } from "@/redux/slices/ugoSlice";

export function Header(props) {
  const pathname = usePathname();
  const { handleSearch } = props;

  const [searchQuery, setSearchQuery] = useState("");
  const [searchResults, setSearchResults] = useState([]);
  const [showSearchResults, setShowSearchResults] = useState(false);

 
  const searchContainerRef = useRef(null);
  const dispatch = useDispatch(); // Create a dispatch function for Redux actions

  const updateSuggestedOptions = (userInput) => {
    const filteredResults = allSearchResults.filter((result) => {
      const lowercaseResult = result.toLowerCase();
      const lowercaseInput = userInput.toLowerCase();
      return lowercaseResult.includes(lowercaseInput);
    });

    setSearchResults(filteredResults);
    setShowSearchResults(true);

    const selectedResult = filteredResults[0];
    const activeStepIndex = UGO_CONTENT.findIndex((content) =>
      content.key.includes(selectedResult)
    );

    dispatch(setActiveStepIndex(activeStepIndex));
    dispatch(setActiveContent(selectedResult));
  };

  const allSearchResults = [
    "Usluge",
    "Galerija",
    "Kontakt",
    "Software",
    "O nama",
    "Ugostiteljstvo",
    "Koristenje u lokalu",
  ];

  useEffect(() => {
    const script = document.createElement("script");
    script.src = "//js-eu1.hs-scripts.com/143256357.js";
    script.type = "text/javascript";
    script.async = true;
    script.defer = true;
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  const links = [
    { name: "Početna stranica", href: "/" },
    { name: "O nama", href: "/o-nama" },
    // Add more navigation links as needed
  ];

  const closeSearchOptions = (e) => {
    if (
      searchContainerRef.current &&
      !searchContainerRef.current.contains(e.target)
    ) {
      setShowSearchResults(false);
    }
  };

  useEffect(() => {
    document.addEventListener("click", closeSearchOptions);

    return () => {
      document.removeEventListener("click", closeSearchOptions);
    };
  }, []);

  return (
    <>
      <Popover
        as="header"
        className={({ open }) =>
          clsx(
            { "fixed inset-0 z-40 overflow-y-auto": open },
            "bg-white shadow-lg lg:static lg:overflow-y-visible"
          )
        }
      >
        {({ open }) => (
          <>
            <div className="mx-auto max-w-large px-4 sm:px-6 lg:px-8">
              <div className="relative flex justify-between lg:gap-8 xl:grid xl:grid-cols-12">
                <div className="flex md:absolute md:inset-y-0 md:left-0 lg:static xl:col-span-1">
                  <div className="flex flex-shrink-0 items-center">
                    <a href="/">
                      <Logo className="mx-auto h-10 w-auto" />
                    </a>
                  </div>
                </div>
                {handleSearch && (
                  <div className="min-w-0 flex-1 md:px-8 lg:px-0 xl:col-span-7">
                    <div className="flex items-center px-6 py-4 md:mx-auto md:max-w-3xl lg:mx-0 lg:max-w-none xl:px-0">
                      <div className="w-full">
                        <label htmlFor="pretraga" className="sr-only">
                          Pretraga
                        </label>
                        <div className="relative">
                          <div className="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
                            <MagnifyingGlassIcon
                              className="h-5 w-5 text-gray-400"
                              aria-hidden="true"
                            />
                          </div>
                          <input
                            id="pretraga"
                            name="pretraga"
                            className="block w-full rounded-md border-0 bg-white py-1.5 pl-10 pr-3 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6"
                            placeholder="Pretraga"
                            type="search"
                            value={searchQuery}
                            onChange={(e) => {
                              setSearchQuery(e.target.value);
                              updateSuggestedOptions(e.target.value);
                            }}
                          />
                          <button
                            onClick={/*handleSearch*/ updateSuggestedOptions}
                            className="absolute inset-y-0 right-0 px-3 py-1.5 text-white bg-primary rounded-md hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                          >
                            Pretraži
                          </button>
                        </div>
                      </div>
                    </div>
                  </div>
                )}
                <div className="flex items-center md:absolute md:inset-y-0 md:right-0 lg:hidden">
                  <Popover.Button className="relative -mx-2 inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
                    <span className="absolute -inset-0.5" />
                    <span className="sr-only">Open menu</span>
                    {open ? (
                      <XMarkIcon className="block h-6 w-6" aria-hidden="true" />
                    ) : (
                      <Bars3Icon className="block h-6 w-6" aria-hidden="true" />
                    )}
                  </Popover.Button>
                </div>
                <div className="hidden lg:flex lg:items-center lg:justify-end xl:col-span-4">
                  <a
                    href="/"
                    className={clsx(
                      { "bg-primary text-white": pathname === "/" },
                      { "text-primary": pathname !== "/" },
                      "ml-6 inline-flex items-center rounded-lg pt-2 pb-2 pr-4 pl-4 text-sm font-semibold"
                    )}
                  >
                    Početna
                  </a>
                  <a
                    href="/o-nama"
                    className={clsx(
                      { "bg-primary text-white": pathname === "/o-nama" },
                      {
                        "text-primary hover:text-secondary":
                          pathname !== "/o-nama",
                      },
                      "ml-6 inline-flex items-center rounded-lg pt-2 pb-2 pr-4 pl-4 text-sm text-primary font-semibold"
                    )}
                  >
                    O nama
                  </a>
                  <Menu as="div" className="relative ml-5 flex-shrink-0">
                    <div>
                      <Menu.Button className="relative flex rounded-full bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
                        <span className="absolute -inset-1.5" />
                        <span className="sr-only">Open user menu</span>
                        {/* <img className="h-8 w-8 rounded-full" src={user.imageUrl} alt="" /> */}
                      </Menu.Button>
                    </div>
                    <Transition
                      as={Fragment}
                      enter="transition ease-out duration-100"
                      enterFrom="transform opacity-0 scale-95"
                      enterTo="transform opacity-100 scale-100"
                      leave="transition ease-in duration-75"
                      leaveFrom="transform opacity-100 scale-100"
                      leaveTo="transform opacity-0 scale-95"
                    >
                      <Menu.Items className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
                        {[].map((item) => (
                          <Menu.Item key={item.name}>
                            {({ active }) => (
                              <a
                                href={item.href}
                                className={clsx(
                                  { "bg-gray-100": active },
                                  "block px-4 py-2 text-sm text-gray-700"
                                )}
                              >
                                {item.name}
                              </a>
                            )}
                          </Menu.Item>
                        ))}
                      </Menu.Items>
                    </Transition>
                  </Menu>
                </div>
              </div>
            </div>

            {/* Search results */}
            {showSearchResults && (
              <div
                ref={searchContainerRef}
                className="absolute top-20 left-1/2 transform -translate-x-1/2 bg-white shadow-lg p-4 mt-2 rounded-md w-3/4 sm:w-2/3 md:w-2/3"
              >
                <h2 className="text-lg font-semibold">Rezultati pretrage:</h2>
                <ul>
                  {searchResults.map((result, index) => (
                    <li key={index} className="mt-2">
                      {result}
                    </li>
                  ))}
                </ul>
              </div>
            )}
          </>
        )}
      </Popover>
    </>
  );
}

Hero.jsx :

"use client";
import React, { useState } from "react";
import clsx from "clsx";
import { Container } from "@/components/Container";
import RightArrowNav from "@/images/icons/right-arrow-nav.svg";
import LeftArrowNav from "@/images/icons/left-arrow-nav.svg";
import ContactForm from "./ContactForm";
import { useSelector, useDispatch } from "react-redux";
import { setActiveStepIndex } from "@/redux/slices/ugoSlice";

const modules = [
  {
    name: "UGO - ugostiteljstvo",
  },
];

const UGO_CONTENT = [
  {
    key: "step-1",
    image: "/images/download.jpeg",
    title: "Step 1",
  },
  {
    key: "step-2",
    image: "/images/download1.jpeg",
    title: "Step 2",
  },
  {
    key: "step-3",
    image: "/images/bg1.jpg",
    title: "Step 3",
  },
];

export function Hero() {
  const [showContactForm, setShowContactForm] = useState(false);
  const activeItemIndex = useSelector((state) => state.ugo.activeStepIndex);
  const activeContent = useSelector((state) => state.ugo.activeContent);

  const setActiveItemIndex = (index) => {
    // Dispatch the action to update the active step index
    dispatch(setActiveStepIndex(index));
  };

  return (
    <Container className="pb-0 lg:pb-12 pt-0 lg:pt-12 lg:pt-24">
      <div className="flex flex-col lg:flex-row justify-between h-full">
        <div className="flex flex-row justify-center lg:flex-col pt-8 pb-8 gap-y-3">
          {modules.map((module, index) => (
            <button
              key={index}
              className={clsx(
                { "bg-primary text-white": activeItemIndex === index },
                { "text-primary": activeItemIndex !== index },
                "rounded-lg pt-2 pb-2 font-semibold w-48 text-center text-sm rounded-md border-2 border-primary hover:bg-primary hover:text-white"
              )}
              onClick={() => setActiveItemIndex(index)}
            >
              {module.name}
            </button>
          ))}
        </div>
        <div className="flex items-center w-full justify-between lg:pl-6 lg:pr-6">
          <div className="hidden items-center lg:flex">
            <LeftArrowNav
              className={clsx(
                { "fill-gray-500 stroke-gray-400": activeItemIndex === 0 },
                { "cursor-pointer": activeItemIndex !== 0 },
                "h-16"
              )}
              onClick={() => {
                if (activeItemIndex !== 0) {
                  setActiveItemIndex(activeItemIndex - 1);
                }
              }}
            />
          </div>
          <div className="flex flex-col h-[80vh] lg:h-full w-full lg:ml-4 lg:mr-4 gap-y-4">
            <div className="w-full h-full border rounded-md">
              <div
                className="w-full h-full"
                style={{
                  backgroundImage: `url(${UGO_CONTENT[activeItemIndex].image})`,
                }}
              />
            </div>
            <div className="flex justify-center gap-x-2">
              <LeftArrowNav
                className={clsx(
                  { "fill-gray-500 stroke-gray-400": activeItemIndex === 0 },
                  { "cursor-pointer": activeItemIndex !== 0 },
                  "w-3 h-8"
                )}
                onClick={() => {
                  if (activeItemIndex !== 0) {
                    setActiveItemIndex(activeItemIndex - 1);
                  }
                }}
              />
              {UGO_CONTENT.map((content, index) => (
                <button
                  key={content.key}
                  className={clsx(
                    { "bg-primary text-white": activeItemIndex === index },
                    { "text-primary": activeItemIndex !== index },
                    "rounded-lg pt-1 pb-1 pl-2 pr-2 text-center text-sm rounded-md border-2 border-primary hover:bg-primary hover:text-white"
                  )}
                  onClick={() => setActiveItemIndex(index)}
                >
                  {content.title}
                </button>
              ))}
              <RightArrowNav
                className={clsx(
                  {
                    "fill-gray-500 stroke-gray-400":
                      activeItemIndex === UGO_CONTENT.length - 1,
                  },
                  {
                    "cursor-pointer":
                      activeItemIndex !== UGO_CONTENT.length - 1,
                  },
                  "w-3 h-8"
                )}
                onClick={() => {
                  if (activeItemIndex !== UGO_CONTENT.length - 1) {
                    setActiveItemIndex(activeItemIndex + 1);
                  }
                }}
              />
            </div>
          </div>
          <div className="hidden items-center lg:flex">
            <RightArrowNav
              className={clsx(
                {
                  "fill-gray-500 stroke-gray-400":
                    activeItemIndex === UGO_CONTENT.length - 1,
                },
                {
                  "cursor-pointer": activeItemIndex !== UGO_CONTENT.length - 1,
                },
                "h-16"
              )}
              onClick={() => {
                if (activeItemIndex !== UGO_CONTENT.length - 1) {
                  setActiveItemIndex(activeItemIndex + 1);
                }
              }}
            />
          </div>
        </div>
        <div className="flex flex-col pt-8 pb-20 justify-between gap-y-3">
          <div className="flex flex-col gap-y-3">
            <button
              className="flex justify-center items-center gap-2 group font-semibold rounded-lg pt-2 pb-2 w-full lg:w-48 text-center text-sm rounded-md border-2 border-primary bg-primary text-white"
              onClick={() => setShowContactForm(!showContactForm)}
            >
              Kontakt forma{" "}
              <RightArrowNav
                className={clsx(
                  { "rotate-90": showContactForm },
                  "h-3 cursor-pointer fill-white group-hover:fill-red"
                )}
              />
            </button>
            {showContactForm && (
              <ContactForm
                showContactForm={showContactForm}
                setShowContactForm={setShowContactForm}
              />
            )}
            <a href="mailto:[email protected]">
              <button className="rounded-lg pt-2 pb-2 font-semibold w-full lg:w-48 text-center text-sm rounded-md border-2 border-primary bg-primary text-white">
                Kontakt mailom
              </button>
            </a>
          </div>
          <div className="p-3 bg-primary text-white rounded-lg text-xs flex flex-col justify-center text-center ">
            <div>Email: [email protected]</div>
            <div>Tel: (+387) 33 xxx xxx</div>
            <div>Lokacija: Grad</div>
          </div>
        </div>
      </div>
    </Container>
  );
}
3
  • 1
    I think you should: 1. Paste as low amount of code as possible to reproduce the error not the "whole" project. 2. Tell what is not working and what you have done already. Commented Sep 18, 2023 at 10:09
  • Hey Adnan, welcome to SO! Since you are a new contributor, let me try to guid you a bit. I read your explanation several times, but still have hard time to figure out what EXACT your problem is. You've listed several requirements but which is the one that produces issue to you? Commented Sep 18, 2023 at 12:57
  • Hello, I have problem when I try to click on one of the search options, I want it to show me either of the steps's content in Hero.jsx on the page, since every of the steps has a picture above it(like image slider). I need to do it using redux, but I am not able to understand it yet. Commented Sep 18, 2023 at 18:08

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.