diff --git a/frontend/src/views/Apps2.jsx b/frontend/src/views/Apps2.jsx
index 828c6bbf..b4573574 100644
--- a/frontend/src/views/Apps2.jsx
+++ b/frontend/src/views/Apps2.jsx
@@ -29,6 +29,7 @@ const searchClient = algoliasearch(
"db08e40265e2941b9a7d8f644b6e5240"
);
+// AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes }) => {
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000";
const appUrl = isCloud ? `/apps/${data.id}` : `https://shuffler.io/apps/${data.id}`;
@@ -42,7 +43,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
height: 96,
borderRadius: 8,
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)",
- // marginBottom: 20,
+ marginBottom: 20,
};
return (
@@ -169,13 +170,13 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
// Component to fetch all public app from the algolia.
-const Hits = memo(({
+const Hits = ({
userdata,
hits,
+ algoliaSelectedCategories,
setIsAnyAppActivated,
searchQuery,
globalUrl,
- setIsLoggedIn,
isLoading,
isLoggedIn,
}) => {
@@ -193,6 +194,16 @@ const Hits = memo(({
}
};
+ useEffect(() => {
+ console.log("searchQuery", searchQuery)
+ console.log("hits", hits)
+ }, [searchQuery, hits])
+
+
+ const filteredHits = hits?.filter(hit => {
+ if (algoliaSelectedCategories?.length === 0) return true; // If no categories are selected, show all hits
+ return hit.categories?.some(category => algoliaSelectedCategories.includes(category));
+ });
// const fetchUserData = useCallback(async () => {
// try {
@@ -281,237 +292,242 @@ const Hits = memo(({
return () => clearTimeout(timer);
}, []);
- const memoizedHits = useMemo(() => hits, [hits]);
return (
{!isLoading ? (
- {memoizedHits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? (
+ {filteredHits?.length === 0 && searchQuery.length >= 0 && showNoAppFound ? (
No Apps Found
) : (
);
-});
+}
+// Main Apps Component
const Apps2 = (props) => {
const { globalUrl, isLoaded, serverside, userdata, isLoggedIn } = props;
let navigate = useNavigate();
@@ -530,11 +547,13 @@ const Apps2 = (props) => {
const location = useLocation();
const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState("");
+ const [algoliaSelectedCategories, setAlgoliaSelectedCategories] = useState([]);
const [selectedLabel, setSelectedLabel] = useState("");
+ const [algoliaSelectedLabels, setAlgoliaSelectedLabels] = useState([]);
const [currTab, setCurrTab] = useState(0);
const [categories, setCategories] = useState([]);
const [labels, setLabels] = useState([]);
- const [isLoading, setIsLoading] = useState(true);
+ const [isLoading, setIsLoading] = useState(false);
const [userApps, setUserApps] = useState([]);
const [orgApps, setOrgApps] = useState([]);
const [selectedCategoryForUsersAndOgsApps, setselectedCategoryForUsersAndOgsApps] = useState([]);
@@ -542,13 +561,12 @@ const Apps2 = (props) => {
const [appsToShow, setAppsToShow] = useState([]);
const [deactivatedIndexes, setDeactivatedIndexes] = React.useState([]);
const [IsAnyAppActivated, setIsAnyAppActivated] = useState(false);
-
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1);
var counted = 0;
const [showNoAppFound, setShowNoAppFound] = useState(false);
- const CustomHits = connectHits(Hits)
+ // Set the current tab based on the query parameter
useEffect(() => {
const queryParams = new URLSearchParams(location.search);
const tabParam = queryParams.get('tab');
@@ -560,10 +578,13 @@ const Apps2 = (props) => {
} else {
setCurrTab(2);
}
+ } else {
+ setCurrTab(0);
}
}, [location.search]);
+ // Fetch apps based on the current tab : 0 -> org_apps, 1 -> my_apps, 2 -> all_apps
useEffect(() => {
const fetchApps = async () => {
const baseUrl = globalUrl;
@@ -589,9 +610,12 @@ const Apps2 = (props) => {
const data = await response.json();
if (currTab === 1) {
console.log("data from userApps", data)
+ setAppsToShow(data);
setUserApps(data);
setIsLoading(false);
} else if (currTab === 0) {
+ console.log("data from orgApps", data)
+ setAppsToShow(data);
setOrgApps(data);
setIsLoading(false);
}
@@ -601,9 +625,20 @@ const Apps2 = (props) => {
};
fetchApps();
- }, [currTab, globalUrl]); // Added globalUrl to dependencies to avoid stale closures
+ }, [currTab, globalUrl, location.search]); // Added globalUrl to dependencies to avoid stale closures
+
+ useEffect(() => {
+ setSearchQuery("");
+ }, [currTab])
+ // Find top categories and tags based on the current tab
+ useEffect(() => {
+ if (currTab === 0) {
+ setCategories(findTopCategories());
+ setLabels(findTopTags());
+ }
+ }, [currTab, appsToShow])
useEffect(() => {
@@ -612,13 +647,13 @@ const Apps2 = (props) => {
}
}, [serverside]);
-
+
const findTopCategories = () => {
const categoryCountMap = {};
-
+ const apps = currTab === 1 ? userApps : orgApps;
// Check if userAndOrgsApp is an array before iterating over it and Find top 10 Category from the apps
- if (Array.isArray(appsToShow)) {
- appsToShow.forEach((app) => {
+ if (Array.isArray(apps)) {
+ apps.forEach((app) => {
const categories = app.categories;
if (categories && categories.length > 0) {
@@ -643,9 +678,10 @@ const Apps2 = (props) => {
const findTopTags = () => {
const tagCountMap = {};
-
- if (Array.isArray(appsToShow)) {
- appsToShow.forEach((app) => {
+ const apps = currTab === 1 ? userApps : orgApps;
+
+ if (Array.isArray(apps)) {
+ apps.forEach((app) => {
const tags = app.tags;
if (tags && tags.length > 0) {
tags.forEach((tag) => {
@@ -666,42 +702,47 @@ const Apps2 = (props) => {
return topTags;
};
-
+
const handleCreateApp = () => {
navigate('/create-app');
};
- //Search app base on app name, category and tag
- const filteredUserAppdata = Array.isArray(appsToShow) ? appsToShow.filter((app) => {
- const matchesSearchQuery = (
- searchQuery === "" ||
- app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
- (app.tags && app.tags.some(tag =>
- tag.toLowerCase().includes(searchQuery.toLowerCase())
- )) ||
- (app.categories && app.categories.some((category) =>
- category.toLowerCase().includes(searchQuery.toLowerCase())
- ))
- );
+ useEffect(() => {
+ const apps = currTab === 1 ? userApps : orgApps;
+ // Search app based on app name, category, and tag
+ const filteredUserAppdata = Array.isArray(apps) ? apps.filter((app) => {
- const matchesSelectedCategories = (
- selectedCategoryForUsersAndOgsApps.length === 0 ||
- (app.categories && app.categories.some(category =>
- selectedCategoryForUsersAndOgsApps.includes(category)
- ))
- );
+ const matchesSearchQuery = (
+ searchQuery === "" || // If searchQuery is empty, match all apps
+ app.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
+ (app.tags && app.tags.some(tag =>
+ tag.toLowerCase().includes(searchQuery.toLowerCase())
+ )) ||
+ (app.categories && app.categories.some((category) =>
+ category.toLowerCase().includes(searchQuery.toLowerCase())
+ ))
+ );
- const matchesSelectedTags = (
- selectedTagsForUserAndOrgApps.length === 0 ||
- (app.tags && selectedTagsForUserAndOrgApps.some(tag =>
- app.tags.includes(tag)
- ))
- );
+ const matchesSelectedCategories = (
+ selectedCategory === "" || // If no category is selected, match all apps
+ (app.categories && app.categories.some(category =>
+ selectedCategory.includes(category)
+ ))
+ );
+ const matchesSelectedTags = (
+ selectedLabel === "" || // If no label is selected, match all apps
+ (app.tags && app.tags.some(tag =>
+ tag.toLowerCase().includes(selectedLabel.toLowerCase())
+ ))
+ );
- return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
- }) : [];
+ return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
+ }) : [];
+
+ setAppsToShow(filteredUserAppdata);
+ }, [searchQuery, selectedCategory, selectedLabel]);
const handleTabChange = (newTab) => {
@@ -746,6 +787,104 @@ const Apps2 = (props) => {
+ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
+ const inputRef = React.useRef(null); // Create a ref for the input field
+
+ // Check for query in URL and set it
+ React.useEffect(() => {
+ if (
+ window !== undefined &&
+ window.location !== undefined &&
+ window.location.search !== undefined &&
+ window.location.search !== null
+ ) {
+ const urlSearchParams = new URLSearchParams(window.location.search);
+ const params = Object.fromEntries(urlSearchParams.entries());
+ const foundQuery = params["q"];
+ if (foundQuery !== null && foundQuery !== undefined) {
+ console.log("Got query: ", foundQuery);
+ refine(foundQuery);
+ setSearchQuery(foundQuery); // Use setSearchQuery to update state
+ }
+ }
+ }, [refine, setSearchQuery]); // Add dependencies
+
+ // Use useEffect to focus the input when it mounts or when searchQuery changes
+ React.useEffect(() => {
+ if (inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [searchQuery]); // Focus whenever searchQuery changes
+
+ console.log("searchQuery", searchQuery);
+
+ return (
+ {
+ setSearchQuery(event.target.value); // Update the search query
+ removeQuery("q");
+ refine(event.target.value); // Refine the search
+ }}
+ onKeyDown={(event) => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ }
+ }}
+ limit={5}
+ style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
+ InputProps={{
+ style: {
+ borderRadius: 8,
+ },
+ endAdornment: (
+
+ {searchQuery?.length === 0 ? : (
+ {
+ setSearchQuery(''); // Clear the search query
+ removeQuery("q");
+ refine(''); // Clear the refinement
+ }}
+ />
+ )}
+
+ ),
+ }}
+ />
+ );
+ };
+
+ const CustomSearchBox = connectSearchBox(SearchBox);
+ const CustomHits = connectHits(Hits)
+
+
+ const handleCategoryChange = (selectedValue) => {
+ setAlgoliaSelectedCategories(prev => {
+ if (prev.includes(selectedValue)) {
+ // If the category is already selected, remove it
+ return prev.filter(category => category !== selectedValue);
+ } else {
+ // Otherwise, add it to the selected categories
+ return [...prev, selectedValue];
+ }
+ });
+ };
+
+ useEffect(() => {
+ console.log("algoliaSelectedCategories", algoliaSelectedCategories)
+ }, [algoliaSelectedCategories])
+
+
return (
@@ -765,38 +904,42 @@ const Apps2 = (props) => {
- {
- setSearchQuery(event.currentTarget.value);
- removeQuery("q");
- // refine(event.currentTarget.value);
- }}
- onKeyDown={(event) => {
- if (event.key === "Enter") {
- event.preventDefault();
- }
- }}
- limit={5}
- style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
- InputProps={{
- style: {
- borderRadius: 8,
- },
- endAdornment: (
-
- {
- searchQuery.length === 0 ? :
- }
-
- ),
- }}
- />
- {/* */}
+ {
+ (currTab === 0 || currTab === 1) &&
+ {
+ setSearchQuery(event.target.value);
+ }}
+ onKeyDown={(event) => {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ }
+ }}
+ limit={5}
+ style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
+ InputProps={{
+ style: {
+ borderRadius: 8,
+ },
+ endAdornment: (
+
+ {
+ searchQuery.length === 0 ? :
+ }
+
+ ),
+ }}
+ />
+ }
+ {
+ currTab === 2 &&
+
+ }
@@ -878,74 +1030,86 @@ const Apps2 = (props) => {
{
- currTab === 0 &&
- (orgApps.length > 0 ? (
-
- {
- isLoading ?
- :
- (
- filteredUserAppdata?.map((data, index) => (
-
- ))
- )
- }
+ currTab === 0 && (
+
+ {isLoading ? (
+
+
+
+ ) : (
+ <>
+ {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
+
+ {appsToShow.map((data, index) => (
+
+ ))}
+
+ ) : (
+
+ No apps found
+
+ )}
+ >
+ )}
- ) :
No apps found
)
}
{
currTab === 1 &&
(userApps.length > 0 ? (
-
- {
- isLoading ?
- :
- (
- userApps.map((data, index) => (
-
- ))
- )
- }
+
+
+ {
+ isLoading ?
+ :
+ (
+ userApps.map((data, index) => (
+
+ ))
+ )
+ }
+
- ) :
No apps found
+ ) : !isLoading && (
+
No apps found
+ )
)
}
{
currTab === 2 &&
+
{
hitsPerPage={5}
globalUrl={globalUrl}
searchQuery={searchQuery}
+ algoliaSelectedCategories={algoliaSelectedCategories}
mouseHoverIndex={mouseHoverIndex}
setMouseHoverIndex={setMouseHoverIndex}
/>