HomeFaq.tsx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import { Faq } from "../../../services/content/types";
  2. import { DataCacheKey, staleTime } from "../../../global/constants";
  3. import { useQuery } from "@tanstack/react-query";
  4. import React, { useState, useEffect, useCallback } from "react";
  5. import { contentApi } from "../../../apis/contentApi";
  6. import {
  7. startLoading,
  8. stopLoading,
  9. } from "../../../features/loading/loadingSlice";
  10. import { useAppDispatch } from "../../../hooks/useRedux";
  11. import { useTranslation } from "react-i18next";
  12. const HomeFaq = () => {
  13. const [openFaqIndex, setOpenFaqIndex] = useState<number | null>(0);
  14. const dispatch = useAppDispatch();
  15. const { t } = useTranslation();
  16. const { data: loadFaqsData = [] } = useQuery<Faq[]>({
  17. queryKey: [DataCacheKey.FAQS],
  18. queryFn: async (): Promise<Faq[]> => {
  19. try {
  20. dispatch(startLoading({}));
  21. const res = await contentApi.LoadFaq({
  22. pageNumber: 0,
  23. pageSize: 10,
  24. isFeatured: true,
  25. });
  26. return res.data.faqs as Faq[];
  27. } catch (error) {
  28. console.error(error);
  29. return []; // 🔴 bắt buộc
  30. } finally {
  31. dispatch(stopLoading());
  32. }
  33. },
  34. staleTime: staleTime,
  35. });
  36. const toggleFaq = (index: number) => {
  37. setOpenFaqIndex(openFaqIndex === index ? null : index);
  38. };
  39. return (
  40. <>
  41. <section className="py-16 md:py-24 bg-white px-4 border-t border-slate-50">
  42. <div className="max-w-4xl mx-auto">
  43. <div className="text-center mb-12 md:mb-20">
  44. <h2 className="text-3xl md:text-6xl font-black tracking-tight text-[#EE0434] mb-4">
  45. {t("frequently")}{" "}
  46. <span className="text-slate-900">{t("askedQuestions")}</span>
  47. </h2>
  48. <p className="text-slate-500 text-sm md:text-xl font-medium">
  49. {t("weAreAlwaysHereToSupportYou")}
  50. </p>
  51. </div>
  52. <div className="space-y-4">
  53. {loadFaqsData.map((faq, index) => (
  54. <div key={index} className="border-b border-slate-100">
  55. <button
  56. onClick={() => toggleFaq(index)}
  57. className="w-full flex justify-between items-center py-6 text-left group transition-all"
  58. >
  59. <span
  60. className={`text-base md:text-2xl font-black transition-colors ${
  61. openFaqIndex === index
  62. ? "text-[#EE0434]"
  63. : "text-slate-800 group-hover:text-[#EE0434]"
  64. }`}
  65. >
  66. {faq.question}
  67. </span>
  68. <div
  69. className={`shrink-0 w-6 h-6 md:w-8 md:h-8 flex items-center justify-center transition-all duration-500 ${
  70. openFaqIndex === index
  71. ? "text-[#EE0434] rotate-180"
  72. : "text-slate-300"
  73. }`}
  74. >
  75. <svg
  76. className="w-5 h-5 md:w-7 md:h-7"
  77. fill="none"
  78. stroke="currentColor"
  79. viewBox="0 0 24 24"
  80. >
  81. <path
  82. strokeLinecap="round"
  83. strokeLinejoin="round"
  84. strokeWidth={3}
  85. d="M19 9l-7 7-7-7"
  86. />
  87. </svg>
  88. </div>
  89. </button>
  90. <div
  91. className={`grid transition-all duration-500 ease-in-out ${
  92. openFaqIndex === index
  93. ? "grid-rows-[1fr] opacity-100"
  94. : "grid-rows-[0fr] opacity-0"
  95. }`}
  96. >
  97. <div className="overflow-hidden">
  98. {/* show html */}
  99. <div
  100. dangerouslySetInnerHTML={{ __html: faq.answer }}
  101. className="text-slate-600 text-sm md:text-xl leading-relaxed font-medium pb-8"
  102. />
  103. {/* <p className="text-slate-600 text-sm md:text-xl leading-relaxed font-medium pb-8">
  104. {faq.answer}
  105. </p> */}
  106. </div>
  107. </div>
  108. </div>
  109. ))}
  110. </div>
  111. </div>
  112. </section>
  113. </>
  114. );
  115. };
  116. export default HomeFaq;