| 1 |
import { useQuery } from "@tanstack/react-query"; |
| 2 |
import React, { useEffect, useState } from "react"; |
| 3 |
import { Droppable } from "react-beautiful-dnd"; |
| 4 |
import EmptyCategory from "../utils/EmptyCategory"; |
| 5 |
import FaqLoader from "../utils/FaqLoader"; |
| 6 |
import { faqOrdering } from "../utils/reOrder"; |
| 7 |
import { getAllFaqBasedOnCategory, reOrderFaqList } from "./../utils/function"; |
| 8 |
import Faq from "./Faq"; |
| 9 |
import SettingsLoader from "../utils/SettingsLoader"; |
| 10 |
import { useFAQScope } from "../context/ScopeContext"; |
| 11 |
|
| 12 |
|
| 13 |
const FaqList = ({ |
| 14 |
category, |
| 15 |
order, |
| 16 |
allFaqCategories, |
| 17 |
changeFaqSort, |
| 18 |
reFetchFaqForCategory, |
| 19 |
createFaqAt, |
| 20 |
categoriesLoading, |
| 21 |
reFetchCategories, |
| 22 |
setCreateFaqAt, |
| 23 |
faqExpanded, |
| 24 |
setFaqExpanded, |
| 25 |
setReFetchFaqForCategory, |
| 26 |
setChangeFaqSort, |
| 27 |
setReFetchData, |
| 28 |
}) => { |
| 29 |
const { taxonomy } = useFAQScope(); |
| 30 |
const { |
| 31 |
isLoading: faqLoading, |
| 32 |
data: allFaqList, |
| 33 |
refetch: reFetchFaqList, |
| 34 |
} = useQuery(["allFaqList", category?.id, taxonomy], getAllFaqBasedOnCategory); |
| 35 |
|
| 36 |
const [sortedFaqList, setSortedFaqList] = useState([]); |
| 37 |
|
| 38 |
useEffect(() => { |
| 39 |
reFetchFaqList(); |
| 40 |
}, [allFaqCategories]); |
| 41 |
|
| 42 |
useEffect(() => { |
| 43 |
setReFetchData({ func: reFetchFaqList }); |
| 44 |
}, [allFaqList]); |
| 45 |
|
| 46 |
useEffect(() => { |
| 47 |
if (!allFaqList?.length) { |
| 48 |
setSortedFaqList([]); |
| 49 |
return; |
| 50 |
} |
| 51 |
|
| 52 |
if (order === 'a_to_z') { |
| 53 |
setSortedFaqList( |
| 54 |
[...allFaqList].sort((a, b) => |
| 55 |
(a.title?.rendered ?? '').localeCompare(b.title?.rendered ?? '') |
| 56 |
) |
| 57 |
); |
| 58 |
return; |
| 59 |
} |
| 60 |
if (order === 'z_to_a') { |
| 61 |
setSortedFaqList( |
| 62 |
[...allFaqList].sort((a, b) => |
| 63 |
(b.title?.rendered ?? '').localeCompare(a.title?.rendered ?? '') |
| 64 |
) |
| 65 |
); |
| 66 |
return; |
| 67 |
} |
| 68 |
if (order === 'most_recent') { |
| 69 |
setSortedFaqList([...allFaqList].sort((a, b) => b.id - a.id)); |
| 70 |
return; |
| 71 |
} |
| 72 |
if (order === 'least_recent') { |
| 73 |
setSortedFaqList([...allFaqList].sort((a, b) => a.id - b.id)); |
| 74 |
return; |
| 75 |
} |
| 76 |
|
| 77 |
// default / most_questions: use the manual drag-drop order stored in meta. |
| 78 |
const sortingArr = (category?.meta?._betterdocs_faq_order[0] || '') |
| 79 |
.split(',') |
| 80 |
.filter(Boolean) |
| 81 |
.map(Number); |
| 82 |
|
| 83 |
if (sortingArr.length) { |
| 84 |
const ordered = sortingArr |
| 85 |
.map((id) => allFaqList.find((faq) => faq.id === id)) |
| 86 |
.filter(Boolean); |
| 87 |
// Append any FAQs missing from the saved order — e.g. a FAQ created |
| 88 |
// in a group that had no order meta yet (the backend seeds the meta |
| 89 |
// with just the new id), which would otherwise hide every existing |
| 90 |
// FAQ even though the count still includes them. |
| 91 |
const orderedIds = new Set(ordered.map((faq) => faq.id)); |
| 92 |
const rest = allFaqList.filter((faq) => !orderedIds.has(faq.id)); |
| 93 |
setSortedFaqList([...ordered, ...rest]); |
| 94 |
} else { |
| 95 |
setSortedFaqList(allFaqList); |
| 96 |
} |
| 97 |
}, [allFaqList, order, category?.meta?._betterdocs_faq_order[0]]); |
| 98 |
|
| 99 |
useEffect(() => { |
| 100 |
if (changeFaqSort?.destination?.droppableId == category?.id) { |
| 101 |
let updatedFaqsList = faqOrdering(changeFaqSort, sortedFaqList); |
| 102 |
setSortedFaqList(updatedFaqsList); |
| 103 |
reOrderFaqList( |
| 104 |
category?.id, |
| 105 |
updatedFaqsList?.map((data) => data?.id)?.toString() |
| 106 |
).then(() => { |
| 107 |
reFetchCategories(); |
| 108 |
}); |
| 109 |
setChangeFaqSort({}); |
| 110 |
} |
| 111 |
}, [changeFaqSort]); |
| 112 |
|
| 113 |
useEffect(() => { |
| 114 |
if (reFetchFaqForCategory && reFetchFaqForCategory == category?.id) { |
| 115 |
reFetchFaqList(); |
| 116 |
setReFetchFaqForCategory(null); |
| 117 |
} |
| 118 |
}, [reFetchFaqForCategory]); |
| 119 |
|
| 120 |
return ( |
| 121 |
<Droppable droppableId={category?.id.toString()} type="FAQ"> |
| 122 |
{(provided) => ( |
| 123 |
<div |
| 124 |
{...provided.droppableProps} |
| 125 |
ref={provided.innerRef} |
| 126 |
className="bd-faq-list-droppable" |
| 127 |
> |
| 128 |
{!faqLoading ? ( |
| 129 |
sortedFaqList?.length > 0 ? ( |
| 130 |
sortedFaqList?.map((faq, index) => ( |
| 131 |
<Faq |
| 132 |
key={faq?.id} |
| 133 |
data={faq} |
| 134 |
index={index} |
| 135 |
order={order} |
| 136 |
reFetchFaqList={reFetchFaqList} |
| 137 |
category={category?.id} |
| 138 |
categoriesLoading={categoriesLoading} |
| 139 |
allFaqCategories={allFaqCategories} |
| 140 |
reFetchCategories={reFetchCategories} |
| 141 |
setCreateFaqAt={setCreateFaqAt} |
| 142 |
faqExpanded={faqExpanded} |
| 143 |
setFaqExpanded={setFaqExpanded} |
| 144 |
setReFetchFaqForCategory={ |
| 145 |
setReFetchFaqForCategory |
| 146 |
} |
| 147 |
settings={betterdocsFaq?.betterdocs_settings} |
| 148 |
/> |
| 149 |
)) |
| 150 |
) : ( |
| 151 |
createFaqAt !== category?.id && <EmptyCategory /> |
| 152 |
) |
| 153 |
) : ( |
| 154 |
<FaqLoader |
| 155 |
count={ |
| 156 |
(Number(category?.count) || 0) + |
| 157 |
(Number(category?.betterdocs_draft_count) || 0) |
| 158 |
} |
| 159 |
/> |
| 160 |
)} |
| 161 |
{provided.placeholder} |
| 162 |
</div> |
| 163 |
)} |
| 164 |
</Droppable> |
| 165 |
); |
| 166 |
}; |
| 167 |
|
| 168 |
export default FaqList; |
| 169 |
|