Done with the revamp of apps2 page : New look

This commit is contained in:
monilprajapati
2024-12-01 19:12:28 +05:30
parent 6da219f53b
commit e652d0039c
+468 -348
View File
@@ -15,6 +15,7 @@ import {
} from "@mui/material"; } from "@mui/material";
import { Context } from "../context/ContextApi.jsx"; import { Context } from "../context/ContextApi.jsx";
import Add from '@mui/icons-material/Add'; import Add from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import InputAdornment from '@mui/material/InputAdornment'; import InputAdornment from '@mui/material/InputAdornment';
import Search from '@mui/icons-material/Search'; import Search from '@mui/icons-material/Search';
import ClearIcon from '@mui/icons-material/Clear'; import ClearIcon from '@mui/icons-material/Clear';
@@ -34,20 +35,23 @@ const searchClient = algoliasearch(
); );
// AppCard Component // AppCard Component
const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab, handleAppClick }) => { const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl, deactivatedIndexes, currTab, handleAppClick, leftSideBarOpenByClick, userdata }) => {
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "localhost:3000"; 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}`; const appUrl = isCloud ? `/apps/${data.id}` : `https://shuffler.io/apps/${data.id}`;
var canEditApp = userdata.admin === "true" || userdata.id === data?.owner || data?.owner === "" || (userdata.admin === "true" && userdata.active_org.id === data?.reference_org) || !data?.generated
const paperStyle = { const paperStyle = {
backgroundColor: mouseHoverIndex === index ? "rgba(26, 26, 26, 1)" : "#1A1A1A", backgroundColor: mouseHoverIndex === index ? "rgba(26, 26, 26, 1)" : "#212121",
color: "rgba(241, 241, 241, 1)", color: "rgba(241, 241, 241, 1)",
cursor: "pointer", cursor: "pointer",
position: "relative", fontFamily: "Inter",
width: 365, // position: "relative",
width: "100%",
height: 96, height: 96,
borderRadius: 8, borderRadius: 8,
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)", boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)",
marginBottom: 20, marginBottom: 20,
transition: "width 0.3s ease",
}; };
return ( return (
@@ -63,7 +67,7 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
fontSize: 16, fontSize: 16,
overflow: "hidden", overflow: "hidden",
display: "flex", display: "flex",
alignItems: "flex-start", fontFamily: "Inter",
width: '100%', width: '100%',
backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "#212121" backgroundColor: mouseHoverIndex === index ? "#2F2F2F" : "#212121"
}} }}
@@ -92,13 +96,14 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
fontWeight: '400', fontWeight: '400',
overflow: "hidden", overflow: "hidden",
margin: "12px 0", margin: "12px 0",
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" fontFamily: "Inter"
}}> }}>
<div style={{ <div style={{
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
fontWeight: 600,
whiteSpace: "nowrap", whiteSpace: "nowrap",
marginLeft: 8, marginLeft: 8,
gap: 8 gap: 8
@@ -118,13 +123,14 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
overflow: "hidden", overflow: "hidden",
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap", whiteSpace: "nowrap",
width: 230, width: "100%",
textAlign: 'start',
marginLeft: 8, marginLeft: 8,
color: "rgba(158, 158, 158, 1)", color: "rgba(158, 158, 158, 1)",
display: "flex" display: "flex",
justifyContent: 'space-between',
paddingRight: 15,
}}> }}>
<div style={{ minWidth: 120, overflow: "hidden" }}> <div style={{ overflow: "hidden", textAlign: 'start' }}>
{data.generated !== true && data.tags && data.tags.slice(0, 2).map((tag, tagIndex) => ( {data.generated !== true && data.tags && data.tags.slice(0, 2).map((tag, tagIndex) => (
<span key={tagIndex}> <span key={tagIndex}>
{tag} {tag}
@@ -134,44 +140,57 @@ const AppCard = ({ data, index, mouseHoverIndex, setMouseHoverIndex, globalUrl,
</div> </div>
{/* Deactivate button */} {/* Deactivate button */}
{currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && ( {currTab === 0 && !deactivatedIndexes.includes(index) && mouseHoverIndex === index && data.generated === true && (
<Button <div style={{
className="deactivate-button" display: "flex",
style={{ gap: 8
marginLeft: 15, }}>
width: 102, {
height: 35, canEditApp && (
borderRadius: 200, <button style={{ backgroundColor: "rgba(73, 73, 73, 1)", border: "none", cursor: "pointer", color: "white", borderRadius: 6, display: "flex", alignItems: "center", justifyContent: "center" }}>
backgroundColor: "rgba(73, 73, 73, 1)", <EditIcon />
color: "rgba(241, 241, 241, 1)", </button>
textTransform: "none", )
}} }
onClick={(event) => { <Button
event.stopPropagation(); className="deactivate-button"
const url = `${globalUrl}/api/v1/apps/${data.id}/deactivate`; style={{
// marginLeft: 15,
width: 102,
height: 35,
borderRadius: 6,
backgroundColor: "rgba(73, 73, 73, 1)",
color: "rgba(241, 241, 241, 1)",
textTransform: "none",
fontFamily: "Inter"
}}
onClick={(event) => {
event.stopPropagation();
const url = `${globalUrl}/api/v1/apps/${data.id}/deactivate`;
fetch(url, { fetch(url, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Accept': 'application/json', 'Accept': 'application/json',
}, },
credentials: "include", credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.success === false) {
toast.error(responseJson.reason);
} else {
toast.success("App Deactivated Successfully. Reload UI to see updated changes.");
}
}) })
.catch(error => { .then((response) => response.json())
console.log("app error: ", error.toString()); .then((responseJson) => {
}); if (responseJson.success === false) {
}} toast.error(responseJson.reason);
> } else {
Deactivate toast.success("App Deactivated Successfully. Reload UI to see updated changes.");
</Button> }
})
.catch(error => {
console.log("app error: ", error.toString());
});
}}
>
Deactivate
</Button>
</div>
)} )}
</div> </div>
</div> </div>
@@ -192,6 +211,7 @@ const Hits = ({
globalUrl, globalUrl,
isLoading, isLoading,
isLoggedIn, isLoggedIn,
leftSideBarOpenByClick
}) => { }) => {
const [hoverEffect, setHoverEffect] = useState(-1); const [hoverEffect, setHoverEffect] = useState(-1);
const [allActivatedAppIds, setAllActivatedAppIds] = useState(userdata?.active_apps); const [allActivatedAppIds, setAllActivatedAppIds] = useState(userdata?.active_apps);
@@ -330,7 +350,7 @@ const Hits = ({
color: "rgba(241, 241, 241, 1)", color: "rgba(241, 241, 241, 1)",
cursor: "pointer", cursor: "pointer",
position: "relative", position: "relative",
width: 365, width: leftSideBarOpenByClick ? 325 : 365,
height: 96, height: 96,
borderRadius: 8, borderRadius: 8,
boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)", boxShadow: "0px 0px 10px 0px rgba(0, 0, 0, 0.1)",
@@ -374,7 +394,6 @@ const Hits = ({
fontWeight: '400', fontWeight: '400',
overflow: "hidden", overflow: "hidden",
margin: "12px 0", margin: "12px 0",
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)"
}} }}
> >
<div <div
@@ -398,7 +417,7 @@ const Hits = ({
textOverflow: "ellipsis", textOverflow: "ellipsis",
whiteSpace: "nowrap", whiteSpace: "nowrap",
color: "rgba(158, 158, 158, 1)", color: "rgba(158, 158, 158, 1)",
marginTop: 5 marginTop: 5,
}} }}
> >
{data.categories !== null {data.categories !== null
@@ -514,46 +533,7 @@ const Hits = ({
); );
} }
// Custom Category Dropdown Component
const CategoryDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => {
const value = event.target.value;
refine(value);
};
return (
<Select
fullWidth
variant="outlined"
value={currentRefinement}
onChange={handleChange}
displayEmpty
multiple
style={{
width: '100%',
maxWidth: '300px',
borderRadius: '7px',
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Categories'}
>
<MenuItem disabled value="">
All Categories
</MenuItem>
{items.map(item => (
<MenuItem key={item.label} value={item.label}>
<Checkbox checked={currentRefinement.includes(item.label)} />
{item.label} ({item.count})
</MenuItem>
))}
</Select>
);
};
const CustomCategoryDropdown = connectRefinementList(CategoryDropdown);
// Custom SearchBox Component // Custom SearchBox Component
const SearchBox = ({ refine, searchQuery, setSearchQuery }) => { const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
@@ -608,10 +588,11 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
event.preventDefault(); event.preventDefault();
} }
}} }}
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }} style={{ borderRadius: 8, height: 45, fontFamily: "Inter", flex: 1 }}
InputProps={{ InputProps={{
style: { style: {
borderRadius: 8, borderRadius: 8,
height: 45
}, },
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
@@ -637,6 +618,38 @@ const SearchBox = ({ refine, searchQuery, setSearchQuery }) => {
const CustomSearchBox = connectSearchBox(SearchBox); const CustomSearchBox = connectSearchBox(SearchBox);
const CustomHits = connectHits(Hits); const CustomHits = connectHits(Hits);
// Custom Category Dropdown Component
const CategoryDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => {
const value = event.target.value;
refine(value);
};
return (
<Select
fullWidth
variant="outlined"
value={currentRefinement}
onChange={handleChange}
displayEmpty
multiple
style={{ borderRadius: 8, height: 45, fontFamily: "Inter", flex: 1 }}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Categories'}
>
<MenuItem disabled value="" style={{ fontFamily: "Inter" }}>
All Categories
</MenuItem>
{items.map(item => (
<MenuItem key={item.label} value={item.label} style={{ fontFamily: "Inter" }}>
<Checkbox checked={currentRefinement.includes(item.label)} />
{item.label} ({item.count})
</MenuItem>
))}
</Select>
);
};
const CustomCategoryDropdown = connectRefinementList(CategoryDropdown);
// Custom Label Dropdown Component // Custom Label Dropdown Component
const LabelDropdown = ({ items, currentRefinement, refine }) => { const LabelDropdown = ({ items, currentRefinement, refine }) => {
const handleChange = (event) => { const handleChange = (event) => {
@@ -652,15 +665,7 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
onChange={handleChange} onChange={handleChange}
displayEmpty displayEmpty
multiple multiple
style={{ style={{ borderRadius: 8, height: 45, fontFamily: "Inter", flex: 1 }}
width: '100%',
maxWidth: '300px',
borderRadius: '7px',
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Labels'} renderValue={(selected) => selected.length ? selected.join(', ') : 'All Labels'}
> >
<MenuItem disabled value=""> <MenuItem disabled value="">
@@ -675,9 +680,44 @@ const LabelDropdown = ({ items, currentRefinement, refine }) => {
</Select> </Select>
); );
}; };
const CustomLabelDropdown = connectRefinementList(LabelDropdown); const CustomLabelDropdown = connectRefinementList(LabelDropdown);
// New filter function
const filterApps = (apps, searchQuery, selectedCategory, selectedLabel) => {
if (!Array.isArray(apps)) return [];
return apps.filter((app) => {
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 matchesSelectedCategories = (
selectedCategory.length === 0 || // If no category is selected, match all apps
(app.categories && app.categories.some(category =>
selectedCategory.includes(category)
))
);
const matchesSelectedTags = (
selectedLabel.length === 0 || // If no label is selected, match all apps
(app.tags && app.tags.some(tag =>
selectedLabel.includes(tag)
))
);
return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
});
};
// Main Apps Component // Main Apps Component
const Apps2 = (props) => { const Apps2 = (props) => {
const { globalUrl, isLoaded, serverside, userdata, isLoggedIn, checkLogin } = props; const { globalUrl, isLoaded, serverside, userdata, isLoggedIn, checkLogin } = props;
@@ -803,14 +843,16 @@ const Apps2 = (props) => {
} }
}, [currTab, globalUrl, userdata?.id]); // Remove location.search dependency }, [currTab, globalUrl, userdata?.id]); // Remove location.search dependency
useEffect(() => { // useEffect(() => {
setSearchQuery(""); // // setSearchQuery("");
}, [currTab]) // setSelectedCategory([]);
// setSelectedLabel([]);
// }, [currTab])
// Find top categories and tags based on the current tab // Find top categories and tags based on the current tab
useEffect(() => { useEffect(() => {
if (currTab === 0) { if (currTab === 0 || currTab === 1) {
setCategories(findTopCategories()); setCategories(findTopCategories());
setLabels(findTopTags()); setLabels(findTopTags());
} }
@@ -881,76 +923,81 @@ const Apps2 = (props) => {
const handleCreateApp = (e) => { const handleCreateApp = (e) => {
e.preventDefault(); e.preventDefault();
setOpenModal(true); // setOpenModal(true);
}; };
useEffect(() => { useEffect(() => {
const apps = currTab === 1 ? userApps : orgApps; const apps = currTab === 1 ? userApps : orgApps;
// Search app based on app name, category, and tag const filteredUserAppdata = filterApps(apps, searchQuery, selectedCategory, selectedLabel);
const filteredUserAppdata = Array.isArray(apps) ? apps.filter((app) => {
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 matchesSelectedCategories = (
selectedCategory.length === 0 || // If no category is selected, match all apps
(app.categories && app.categories.some(category =>
selectedCategory.includes(category)
))
);
const matchesSelectedTags = (
selectedLabel.length === 0 || // If no label is selected, match all apps
(app.tags && app.tags.some(tag =>
selectedLabel.includes(tag)
))
);
return matchesSearchQuery && matchesSelectedCategories && matchesSelectedTags;
}) : [];
setAppsToShow(filteredUserAppdata); setAppsToShow(filteredUserAppdata);
}, [searchQuery, selectedCategory, selectedLabel]); }, [searchQuery, selectedCategory, selectedLabel, currTab]);
const handleTabChange = (newTab) => { const handleTabChange = (newTab) => {
setCurrTab(newTab); setCurrTab(newTab);
// Apply filters immediately when changing tabs
if (newTab === 0) { if (newTab === 0) {
setAppsToShow(orgApps) const filteredOrgApps = filterApps(orgApps, searchQuery, selectedCategory, selectedLabel);
const categories = findTopCategories(); setAppsToShow(filteredOrgApps);
const labels = findTopTags(); } else if (newTab === 1) {
setCategories(categories); const filteredUserApps = filterApps(userApps, searchQuery, selectedCategory, selectedLabel);
setLabels(labels); setAppsToShow(filteredUserApps);
}
if (newTab === 1) {
setAppsToShow(userApps)
} }
// Update URL query params
const newQueryParam = newTab === 0 ? 'org_apps' : newTab === 1 ? 'my_apps' : 'all_apps'; const newQueryParam = newTab === 0 ? 'org_apps' : newTab === 1 ? 'my_apps' : 'all_apps';
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
queryParams.set('tab', newQueryParam); queryParams.set('tab', newQueryParam);
queryParams.delete('q'); // Only remove 'q' param if search is empty
if (!searchQuery) {
queryParams.delete('q');
}
window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`); window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`);
}; };
// Update useEffect to handle initial load and URL search params
useEffect(() => {
const queryParams = new URLSearchParams(location.search);
const searchParam = queryParams.get('q');
if (searchParam) {
setSearchQuery(searchParam);
}
}, []);
// Update useEffect for filtering to handle both tabs
useEffect(() => {
if (currTab === 2) return; // Skip for "Discover Apps" tab as it uses Algolia
const apps = currTab === 1 ? userApps : orgApps;
const filteredApps = filterApps(apps, searchQuery, selectedCategory, selectedLabel);
setAppsToShow(filteredApps);
// Update URL with search query
const queryParams = new URLSearchParams(location.search);
if (searchQuery) {
queryParams.set('q', searchQuery);
} else {
queryParams.delete('q');
}
window.history.replaceState({}, '', `${location.pathname}?${queryParams.toString()}`);
}, [searchQuery, selectedCategory, selectedLabel, currTab, userApps, orgApps]);
// Update search input handler to maintain state across tabs
const handleSearchChange = (event) => {
const newSearchQuery = event.target.value;
setSearchQuery(newSearchQuery);
};
const boxStyle = { const boxStyle = {
color: "white", color: "white",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
height: "100%",
width: "100%", width: "100%",
margin: "auto", margin: "auto",
maxWidth: "60%", maxWidth: "70%",
fontFamily: "Inter",
// padding: '20px 380px', // padding: '20px 380px',
}; };
@@ -975,214 +1022,287 @@ const Apps2 = (props) => {
} }
return ( return (
<InstantSearch searchClient={searchClient} indexName="appsearch"> <div style={{ paddingTop: 70, minHeight: 1000, paddingLeft: leftSideBarOpenByClick ? 200 : 0, transition: "padding-left 0.3s ease", backgroundColor: "#1A1A1A" }}>
<AppModal <InstantSearch searchClient={searchClient} indexName="appsearch">
open={openModal} <AppModal
onClose={handleAppModalClose} open={openModal}
app={selectedApp} onClose={handleAppModalClose}
userdata={userdata} app={selectedApp}
globalUrl={globalUrl} userdata={userdata}
/> globalUrl={globalUrl}
<div style={boxStyle}> />
<Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none' }}> <div style={boxStyle}>
Apps <Typography variant="h4" style={{ marginBottom: 20, paddingLeft: 15, textTransform: 'none', fontFamily: "Inter" }}>
</Typography> Apps
<div style={{ borderBottom: '1px solid gray', marginBottom: 30, marginRight: 10 }}> </Typography>
<Tabs <div style={{ borderBottom: '1px solid gray', marginBottom: 30, marginRight: 10 }}>
value={currTab} <Tabs
onChange={(event, newTab) => handleTabChange(newTab)} value={currTab}
TabIndicatorProps={{ style: { height: '3px', borderRadius: 10 } }} onChange={(event, newTab) => handleTabChange(newTab)}
> TabIndicatorProps={{ style: { height: '3px', borderRadius: 10 } }}
<Tab label="Organization Apps" style={{ textTransform: 'none', marginRight: 20 }} /> style={{ fontFamily: "Inter" }}
<Tab label="My Apps" style={{ textTransform: 'none', marginRight: 20 }} /> >
<Tab label="Discover Apps" style={{ textTransform: 'none' }} /> <Tab label="Organization Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: "Inter" }} />
</Tabs> <Tab label="My Apps" style={{ textTransform: 'none', marginRight: 20, fontFamily: "Inter" }} />
</div> <Tab label="Discover Apps" style={{ textTransform: 'none', fontFamily: "Inter" }} />
<div style={{ display: "flex", justifyContent: "space-between", marginBottom: 20 }}> </Tabs>
<div style={{ flex: 1, marginRight: 10 }}> </div>
<div style={{ display: "flex", justifyContent: "space-between", gap: 10, marginBottom: 20, height: 45 }}>
<div style={{ flex: 1, width: '100%', borderRadius: '7px' }}>
{
(currTab === 0 || currTab === 1) &&
<TextField
fullWidth
variant="outlined"
placeholder="Search for apps"
value={searchQuery}
id="shuffle_search_field"
onChange={handleSearchChange}
onKeyDown={(event) => {
if (event.key === "Enter") {
event.preventDefault();
}
}}
limit={5}
InputProps={{
style: {
borderRadius: 8,
height: 45
},
endAdornment: (
<InputAdornment position="end">
{searchQuery.length === 0 ? (
<Search />
) : (
<ClearIcon
style={{ cursor: "pointer" }}
onClick={() => {
setSearchQuery("");
}}
/>
)}
</InputAdornment>
),
}}
/>
}
{
currTab === 2 &&
<CustomSearchBox searchQuery={searchQuery} setSearchQuery={setSearchQuery} />
}
</div>
<div style={{ flex: 1, width: '100%', borderRadius: '7px', position: 'relative' }}>
{currTab === 2 ? (
<CustomCategoryDropdown attribute="categories" />
) : (
<>
<Select
fullWidth
variant="outlined"
value={selectedCategory}
onChange={handleCategoryChange}
displayEmpty
multiple
style={{ borderRadius: 8, height: 45, fontFamily: "Inter" }}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Categories'}
>
<MenuItem disabled value="" style={{ fontFamily: "Inter" }}>
All Categories
</MenuItem>
{categories?.map((category) => (
<MenuItem key={category.category} value={category.category} style={{ fontFamily: "Inter" }}>
<Checkbox checked={selectedCategory.includes(category.category)} />
{category.category}
</MenuItem>
))}
</Select>
{selectedCategory.length > 0 && (
<ClearIcon
style={{
position: 'absolute',
right: 35,
top: '50%',
transform: 'translateY(-50%)',
cursor: 'pointer',
color: 'white',
fontSize: 20,
zIndex: 1000
}}
onClick={() => setSelectedCategory([])}
/>
)}
</>
)}
</div>
<div style={{ flex: 1, width: '100%', borderRadius: '7px', position: 'relative' }}>
{currTab === 2 ? (
<CustomLabelDropdown attribute="action_labels" />
) : (
<>
<Select
fullWidth
variant="outlined"
value={selectedLabel}
onChange={handleLabelChange}
displayEmpty
multiple
style={{ borderRadius: 8, height: 45, fontFamily: "Inter" }}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Labels'}
>
<MenuItem disabled value="" style={{ fontFamily: "Inter" }}>
All Labels
</MenuItem>
{labels?.map((tag) => (
<MenuItem key={tag.tag} value={tag.tag} style={{ fontFamily: "Inter" }}>
<Checkbox checked={selectedLabel.includes(tag.tag)} />
{tag.tag}
</MenuItem>
))}
</Select>
{selectedLabel.length > 0 && (
<ClearIcon
style={{
position: 'absolute',
right: 35,
top: '50%',
transform: 'translateY(-50%)',
cursor: 'pointer',
color: 'white',
fontSize: 20,
zIndex: 1000
}}
onClick={() => setSelectedLabel([])}
/>
)}
</>
)}
</div>
<div style={{ flex: 1 }}>
<Button
variant="contained"
color="primary"
onClick={handleCreateApp}
style={{ height: "100%", width: '100%', borderRadius: '7px', textTransform: 'none', backgroundColor: "#FF8544", color: "#1A1A1A", fontFamily: "Inter" }}
>
<Add style={{ marginRight: 10, color: "#1A1A1A", fontSize: 20 }} />
Create an App
</Button>
</div>
</div>
<div>
{ {
(currTab === 0 || currTab === 1) && currTab === 0 && (
<TextField <div style={{ minHeight: 570 }}>
fullWidth {isLoading ? (
variant="outlined" <div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
placeholder="Search for apps" <CircularProgress />
value={searchQuery} </div>
id="shuffle_search_field" ) : (
onChange={(event) => { <>
setSearchQuery(event.target.value); {appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
}} <div style={{
onKeyDown={(event) => { marginTop: 16,
if (event.key === "Enter") { width: "100%",
event.preventDefault(); display: "grid",
} gridTemplateColumns: "repeat(auto-fill, minmax(365px, 1fr))",
}} gap: "20px",
limit={5} justifyContent: "space-between",
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }} alignItems: "start",
InputProps={{ padding: "0 10px"
style: { }}>
borderRadius: 8, {appsToShow.map((data, index) => (
}, <AppCard
endAdornment: ( key={index}
<InputAdornment position="end"> data={data}
{ index={index}
searchQuery.length === 0 ? <Search /> : <ClearIcon /> mouseHoverIndex={mouseHoverIndex}
} setMouseHoverIndex={setMouseHoverIndex}
</InputAdornment> globalUrl={globalUrl}
), deactivatedIndexes={deactivatedIndexes}
}} currTab={currTab}
/> handleAppClick={handleAppClick}
leftSideBarOpenByClick={leftSideBarOpenByClick}
userdata={userdata}
/>
))}
</div>
) : (
<div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<AppSelection
userdata={userdata}
globalUrl={globalUrl}
appFramework={appFramework}
setAppFramework={setAppFramework}
defaultSearch={defaultSearch}
setDefaultSearch={setDefaultSearch}
checkLogin={checkLogin}
isAppPage={true}
/>
</div>
)}
</>
)}
</div>
)
} }
{
currTab === 1 && (
<div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
{isLoading ? (
<div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<CircularProgress />
</div>
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined ? (
<div style={{
marginTop: 16,
width: "100%",
display: "grid",
gridTemplateColumns: "repeat(auto-fill, minmax(365px, 1fr))",
gap: "20px",
justifyContent: "space-between",
alignItems: "start",
padding: "0 10px"
}}>
{appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} userdata={userdata}
handleAppClick={handleAppClick} leftSideBarOpenByClick={leftSideBarOpenByClick}
/>
))}
</div>
) : (
<div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<Typography variant="body1">No Apps Found</Typography>
</div>
)}
</>
)}
</div>
)
}
{ {
currTab === 2 && currTab === 2 &&
<CustomSearchBox searchQuery={searchQuery} setSearchQuery={setSearchQuery} /> <CustomHits
isLoggedIn={isLoggedIn}
userdata={userdata}
handleAppClick={handleAppClick}
setIsAnyAppActivated={setIsAnyAppActivated}
hitsPerPage={5}
globalUrl={globalUrl}
searchQuery={searchQuery}
mouseHoverIndex={mouseHoverIndex}
setMouseHoverIndex={setMouseHoverIndex}
leftSideBarOpenByClick={leftSideBarOpenByClick}
/>
} }
</div> </div>
<div style={{ flex: 1, marginRight: 10 }}> </div >
{currTab === 2 ? ( <Configure clickAnalytics />
<CustomCategoryDropdown attribute="categories" /> </InstantSearch>
) : ( </div>
<Select
fullWidth
variant="outlined"
value={selectedCategory}
onChange={handleCategoryChange}
displayEmpty
multiple
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", maxWidth: "300px" }}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Categories'}
>
<MenuItem disabled value="">
All Categories
</MenuItem>
{categories?.map((category) => (
<MenuItem key={category.category} value={category.category}>
<Checkbox checked={selectedCategory.includes(category.category)} />
{category.category}
</MenuItem>
))}
</Select>
)}
</div>
<div style={{ flex: 1, marginRight: 10 }}>
{currTab === 2 ? (
<CustomLabelDropdown attribute="action_labels" />
) : (
<Select
fullWidth
variant="outlined"
value={selectedLabel}
onChange={handleLabelChange}
displayEmpty
multiple
style={{ width: '100%', borderRadius: '7px', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)", maxWidth: "300px" }}
renderValue={(selected) => selected.length ? selected.join(', ') : 'All Labels'}
>
<MenuItem disabled value="">
All Labels
</MenuItem>
{labels?.map((tag) => (
<MenuItem key={tag.tag} value={tag.tag}>
<Checkbox checked={selectedLabel.includes(tag.tag)} />
{tag.tag}
</MenuItem>
))}
</Select>
)}
</div>
<div style={{ flex: 1, marginRight: 10 }}>
<Button
variant="contained"
color="primary"
onClick={handleCreateApp}
style={{ height: "100%", width: '100%', borderRadius: '7px', textTransform: 'none', fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)" }}
>
<Add style={{ marginRight: 10 }} />
Create an App
</Button>
</div>
</div>
<div>
{
currTab === 0 && (
<div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
{isLoading ? (
<div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<CircularProgress />
</div>
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined && !isLoading ? (
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}>
{appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab} handleAppClick={handleAppClick} />
))}
</div>
) : (
<div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<AppSelection
userdata={userdata}
globalUrl={globalUrl}
appFramework={appFramework}
setAppFramework={setAppFramework}
defaultSearch={defaultSearch}
setDefaultSearch={setDefaultSearch}
checkLogin={checkLogin}
isAppPage={true}
/>
</div>
)}
</>
)}
</div>
)
}
{
currTab === 1 && (
<div style={{ minHeight: 570, overflowY: "auto", overflowX: "hidden" }}>
{isLoading ? (
<div style={{ width: "100%", textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<CircularProgress />
</div>
) : (
<>
{appsToShow?.length > 0 && appsToShow !== undefined ? (
<div style={{ rowGap: 16, columnGap: 16, marginTop: 16, display: "flex", flexWrap: "wrap", justifyContent: "flex-start", maxHeight: 570, scrollbarWidth: "thin", scrollbarColor: "#494949 #2f2f2f" }}>
{appsToShow.map((data, index) => (
<AppCard key={index} data={data} index={index} mouseHoverIndex={mouseHoverIndex} setMouseHoverIndex={setMouseHoverIndex} globalUrl={globalUrl} deactivatedIndexes={deactivatedIndexes} currTab={currTab}
handleAppClick={handleAppClick}
/>
))}
</div>
) : (
<div style={{ width: "100%", marginTop: 60, textAlign: "center", display: "flex", justifyContent: "center", alignItems: "center" }}>
<Typography variant="body1">No Apps Found</Typography>
</div>
)}
</>
)}
</div>
)
}
{
currTab === 2 &&
<CustomHits
isLoggedIn={isLoggedIn}
userdata={userdata}
handleAppClick={handleAppClick}
setIsAnyAppActivated={setIsAnyAppActivated}
hitsPerPage={5}
globalUrl={globalUrl}
searchQuery={searchQuery}
mouseHoverIndex={mouseHoverIndex}
setMouseHoverIndex={setMouseHoverIndex}
/>
}
</div>
</div >
<Configure clickAnalytics />
</InstantSearch>
); );
}; };