Skip to content

Commit

Permalink
Feat: pinned apps on top of all apps
Browse files Browse the repository at this point in the history
  • Loading branch information
katspaugh committed Oct 27, 2023
1 parent 04cd78f commit 9095685
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 81 deletions.
64 changes: 30 additions & 34 deletions src/components/safe-apps/SafeAppList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,28 @@ import { useCallback } from 'react'
import type { SafeAppData } from '@safe-global/safe-gateway-typescript-sdk'
import classnames from 'classnames'

import SafeAppsFilters from '@/components/safe-apps/SafeAppsFilters'
import SafeAppCard, { GRID_VIEW_MODE } from '@/components/safe-apps/SafeAppCard'
import type { SafeAppsViewMode } from '@/components/safe-apps/SafeAppCard'
import AddCustomSafeAppCard from '@/components/safe-apps/AddCustomSafeAppCard'
import SafeAppPreviewDrawer from '@/components/safe-apps/SafeAppPreviewDrawer'
import SafeAppsListHeader from '@/components/safe-apps/SafeAppsListHeader'
import SafeAppsZeroResultsPlaceholder from '@/components/safe-apps/SafeAppsZeroResultsPlaceholder'
import useSafeAppsFilters from '@/hooks/safe-apps/useSafeAppsFilters'
import useSafeAppPreviewDrawer from '@/hooks/safe-apps/useSafeAppPreviewDrawer'
import css from './styles.module.css'
import { Skeleton } from '@mui/material'
import useLocalStorage from '@/services/local-storage/useLocalStorage'
import { useOpenedSafeApps } from '@/hooks/safe-apps/useOpenedSafeApps'
import { motion, AnimatePresence } from 'framer-motion'

type SafeAppListProps = {
safeAppsList: SafeAppData[]
safeAppsListLoading?: boolean
bookmarkedSafeAppsId?: Set<number>
onBookmarkSafeApp?: (safeAppId: number) => void
showFilters?: boolean
addCustomApp?: (safeApp: SafeAppData) => void
removeCustomApp?: (safeApp: SafeAppData) => void
title: string
query?: string
}

const VIEW_MODE_KEY = 'SafeApps_viewMode'
Expand All @@ -33,18 +33,16 @@ const SafeAppList = ({
safeAppsListLoading,
bookmarkedSafeAppsId,
onBookmarkSafeApp,
showFilters,
addCustomApp,
removeCustomApp,
title,
query,
}: SafeAppListProps) => {
const [safeAppsViewMode = GRID_VIEW_MODE, setSafeAppsViewMode] = useLocalStorage<SafeAppsViewMode>(VIEW_MODE_KEY)
const { isPreviewDrawerOpen, previewDrawerApp, openPreviewDrawer, closePreviewDrawer } = useSafeAppPreviewDrawer()
const { openedSafeAppIds } = useOpenedSafeApps()

const { filteredApps, query, setQuery, setSelectedCategories, setOptimizedWithBatchFilter, selectedCategories } =
useSafeAppsFilters(safeAppsList)

const showZeroResultsPlaceholder = query && filteredApps.length === 0
const showZeroResultsPlaceholder = query && safeAppsList.length === 0

const handleSafeAppClick = useCallback(
(safeApp: SafeAppData) => {
Expand All @@ -59,20 +57,10 @@ const SafeAppList = ({

return (
<>
{/* Safe Apps Filters */}
{showFilters && (
<SafeAppsFilters
onChangeQuery={setQuery}
onChangeFilterCategory={setSelectedCategories}
onChangeOptimizedWithBatch={setOptimizedWithBatchFilter}
selectedCategories={selectedCategories}
safeAppsList={safeAppsList}
/>
)}

{/* Safe Apps List Header */}
<SafeAppsListHeader
amount={filteredApps.length}
title={title}
amount={safeAppsList.length}
safeAppsViewMode={safeAppsViewMode}
setSafeAppsViewMode={setSafeAppsViewMode}
/>
Expand All @@ -98,20 +86,28 @@ const SafeAppList = ({
</li>
))}

{/* Flat list filtered by search query */}
{filteredApps.map((safeApp) => (
<li key={safeApp.id}>
<SafeAppCard
safeApp={safeApp}
viewMode={safeAppsViewMode}
isBookmarked={bookmarkedSafeAppsId?.has(safeApp.id)}
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
onClickSafeApp={handleSafeAppClick(safeApp)}
openPreviewDrawer={openPreviewDrawer}
/>
</li>
))}
<AnimatePresence>
{/* Flat list filtered by search query */}
{safeAppsList.map((safeApp) => (
<motion.li
key={safeApp.id}
layout
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.8, opacity: 0 }}
transition={{ duration: 0.2 }}
>
<SafeAppCard
safeApp={safeApp}
viewMode={safeAppsViewMode}
isBookmarked={bookmarkedSafeAppsId?.has(safeApp.id)}
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
onClickSafeApp={handleSafeAppClick(safeApp)}
openPreviewDrawer={openPreviewDrawer}
/>
</motion.li>
))}
</AnimatePresence>
</ul>

{/* Zero results placeholder */}
Expand Down
2 changes: 1 addition & 1 deletion src/components/safe-apps/SafeAppList/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
display: grid;
grid-gap: var(--space-3);
list-style-type: none;
padding: 0;
padding: 0 0 var(--space-1);
}

.safeAppsGridViewContainer {
Expand Down
9 changes: 5 additions & 4 deletions src/components/safe-apps/SafeAppsListHeader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,18 @@ import css from './styles.module.css'
import { SAFE_APPS_EVENTS, trackEvent } from '@/services/analytics'

type SafeAppsListHeaderProps = {
title: string
amount?: number
safeAppsViewMode: SafeAppsViewMode
setSafeAppsViewMode: (viewMode: SafeAppsViewMode) => void
}

const SafeAppsListHeader = ({ amount, safeAppsViewMode, setSafeAppsViewMode }: SafeAppsListHeaderProps) => {
const SafeAppsListHeader = ({ title, amount, safeAppsViewMode, setSafeAppsViewMode }: SafeAppsListHeaderProps) => {
return (
<Stack display="flex" flexDirection="row" justifyContent="space-between">
<Stack display="flex" flexDirection="row" justifyContent="space-between" mt={3}>
{/* Safe Apps count */}
<Typography variant="body2" color="primary.light" mb={2} mt={1.5} fontSize="12px" letterSpacing="0.4px">
ALL ({amount || 0})
<Typography variant="body2" color="primary.light" fontWeight="bold">
{title} ({amount || 0})
</Typography>

{/* switch Safe Apps view mode radio buttons */}
Expand Down
4 changes: 0 additions & 4 deletions src/components/sidebar/SidebarNavigation/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,6 @@ export const safeAppsNavItems = [
label: 'All apps',
href: AppRoutes.apps.index,
},
{
label: 'Bookmarked apps',
href: AppRoutes.apps.bookmarked,
},
{
label: 'My custom apps',
href: AppRoutes.apps.custom,
Expand Down
39 changes: 12 additions & 27 deletions src/pages/apps/bookmarked.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,21 @@
import type { NextPage } from 'next'
import Head from 'next/head'

import { useSafeApps } from '@/hooks/safe-apps/useSafeApps'
import SafeAppsHeader from '@/components/safe-apps/SafeAppsHeader'
import SafeAppList from '@/components/safe-apps/SafeAppList'
import SafeAppsSDKLink from '@/components/safe-apps/SafeAppsSDKLink'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { AppRoutes } from '@/config/routes'

const BookmarkedSafeApps: NextPage = () => {
const {
pinnedSafeApps: bookmarkedSafeApps,
pinnedSafeAppIds: bookmarkedSafeAppsId,
togglePin: onBookmarkSafeApp,
} = useSafeApps()

return (
<>
<Head>
<title>{'Bookmarked Safe Apps'}</title>
</Head>
const router = useRouter()

<SafeAppsSDKLink />
// Redirect to /apps
useEffect(() => {
router.push({ pathname: AppRoutes.apps.index, query: { safe: router.query.safe } })
}, [router])

<SafeAppsHeader />

<main>
<SafeAppList
safeAppsList={bookmarkedSafeApps}
bookmarkedSafeAppsId={bookmarkedSafeAppsId}
onBookmarkSafeApp={onBookmarkSafeApp}
/>
</main>
</>
return (
<Head>
<title>{'Safe{Wallet} – Safe Apps'}</title>
</Head>
)
}

Expand Down
1 change: 1 addition & 0 deletions src/pages/apps/custom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const CustomSafeApps: NextPage = () => {

<main>
<SafeAppList
title="Custom apps"
safeAppsList={customSafeApps}
addCustomApp={addCustomApp}
removeCustomApp={openRemoveCustomAppModal}
Expand Down
46 changes: 35 additions & 11 deletions src/pages/apps/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
import { useEffect } from 'react'
import { useEffect, useMemo } from 'react'

import { useSafeApps } from '@/hooks/safe-apps/useSafeApps'
import SafeAppsSDKLink from '@/components/safe-apps/SafeAppsSDKLink'
import SafeAppsHeader from '@/components/safe-apps/SafeAppsHeader'
import SafeAppList from '@/components/safe-apps/SafeAppList'
import { AppRoutes } from '@/config/routes'
import useSafeAppsFilters from '@/hooks/safe-apps/useSafeAppsFilters'
import SafeAppsFilters from '@/components/safe-apps/SafeAppsFilters'

const SafeApps: NextPage = () => {
const router = useRouter()
const { remoteSafeApps, remoteSafeAppsLoading, pinnedSafeApps, pinnedSafeAppIds, togglePin } = useSafeApps()
const { filteredApps, query, setQuery, setSelectedCategories, setOptimizedWithBatchFilter, selectedCategories } =
useSafeAppsFilters(remoteSafeApps)

const {
remoteSafeApps,
remoteSafeAppsLoading,
pinnedSafeAppIds: bookmarkedSafeAppsId,
togglePin: onBookmarkSafeApp,
} = useSafeApps()
const nonPinnedApps = useMemo(
() => remoteSafeApps.filter((app) => !pinnedSafeAppIds.has(app.id)),
[remoteSafeApps, pinnedSafeAppIds],
)

// Redirect to an individual safe app page if the appUrl is in the query params
useEffect(() => {
Expand All @@ -38,12 +41,33 @@ const SafeApps: NextPage = () => {
<SafeAppsHeader />

<main>
<SafeAppList
{/* Safe Apps Filters */}
<SafeAppsFilters
onChangeQuery={setQuery}
onChangeFilterCategory={setSelectedCategories}
onChangeOptimizedWithBatch={setOptimizedWithBatchFilter}
selectedCategories={selectedCategories}
safeAppsList={remoteSafeApps}
/>

{/* Pinned apps */}
{!query && (
<SafeAppList
title="My pinned apps"
safeAppsList={pinnedSafeApps}
bookmarkedSafeAppsId={pinnedSafeAppIds}
onBookmarkSafeApp={togglePin}
/>
)}

{/* All apps */}
<SafeAppList
title="All apps"
safeAppsList={query ? filteredApps : nonPinnedApps}
safeAppsListLoading={remoteSafeAppsLoading}
bookmarkedSafeAppsId={bookmarkedSafeAppsId}
onBookmarkSafeApp={onBookmarkSafeApp}
showFilters
bookmarkedSafeAppsId={pinnedSafeAppIds}
onBookmarkSafeApp={togglePin}
query={query}
/>
</main>
</>
Expand Down

0 comments on commit 9095685

Please sign in to comment.