satnaing пре 2 година
родитељ
комит
b586f842fe
5 измењених фајлова са 281 додато и 3 уклоњено
  1. 7 0
      src/data/sidelinks.tsx
  2. 12 2
      src/index.css
  3. 110 0
      src/pages/apps/data.tsx
  4. 145 0
      src/pages/apps/index.tsx
  5. 7 1
      src/router.tsx

+ 7 - 0
src/data/sidelinks.tsx

@@ -1,4 +1,5 @@
 import {
+  IconApps,
   IconBarrierBlock,
   IconBoxSeam,
   IconChartHistogram,
@@ -51,6 +52,12 @@ export const sidelinks: SideLink[] = [
     href: '/chats',
     icon: <IconMessages size={18} />,
   },
+  {
+    title: 'Apps',
+    label: '',
+    href: '/apps',
+    icon: <IconApps size={18} />,
+  },
   {
     title: 'Authentication',
     label: '',

+ 12 - 2
src/index.css

@@ -97,9 +97,7 @@
       height: 0;
     }
   }
-}
 
-@layer base {
   * {
     @apply border-border;
   }
@@ -107,3 +105,15 @@
     @apply min-h-svh w-full bg-background text-foreground;
   }
 }
+
+@layer utilities {
+  /* Hide scrollbar for Chrome, Safari and Opera */
+  .no-scrollbar::-webkit-scrollbar {
+    display: none;
+  }
+  /* Hide scrollbar for IE, Edge and Firefox */
+  .no-scrollbar {
+    -ms-overflow-style: none; /* IE and Edge */
+    scrollbar-width: none; /* Firefox */
+  }
+}

+ 110 - 0
src/pages/apps/data.tsx

@@ -0,0 +1,110 @@
+import {
+  IconBrandDiscord,
+  IconBrandDocker,
+  IconBrandFigma,
+  IconBrandGithub,
+  IconBrandGitlab,
+  IconBrandGmail,
+  IconBrandMedium,
+  IconBrandNotion,
+  IconBrandSkype,
+  IconBrandSlack,
+  IconBrandStripe,
+  IconBrandTelegram,
+  IconBrandTrello,
+  IconBrandWhatsapp,
+  IconBrandZoom,
+} from '@tabler/icons-react'
+
+export const apps = [
+  {
+    name: 'Telegram',
+    logo: <IconBrandTelegram />,
+    connected: false,
+    desc: 'Connect with Telegram for real-time communication.',
+  },
+  {
+    name: 'Notion',
+    logo: <IconBrandNotion />,
+    connected: true,
+    desc: 'Effortlessly sync Notion pages for seamless collaboration.',
+  },
+  {
+    name: 'Figma',
+    logo: <IconBrandFigma />,
+    connected: true,
+    desc: 'View and collaborate on Figma designs in one place.',
+  },
+  {
+    name: 'Trello',
+    logo: <IconBrandTrello />,
+    connected: false,
+    desc: 'Sync Trello cards for streamlined project management.',
+  },
+  {
+    name: 'Slack',
+    logo: <IconBrandSlack />,
+    connected: false,
+    desc: 'Integrate Slack for efficient team communication',
+  },
+  {
+    name: 'Zoom',
+    logo: <IconBrandZoom />,
+    connected: true,
+    desc: 'Host Zoom meetings directly from the dashboard.',
+  },
+  {
+    name: 'Stripe',
+    logo: <IconBrandStripe />,
+    connected: false,
+    desc: 'Easily manage Stripe transactions and payments.',
+  },
+  {
+    name: 'Gmail',
+    logo: <IconBrandGmail />,
+    connected: true,
+    desc: 'Access and manage Gmail messages effortlessly.',
+  },
+  {
+    name: 'Medium',
+    logo: <IconBrandMedium />,
+    connected: false,
+    desc: 'Explore and share Medium stories on your dashboard.',
+  },
+  {
+    name: 'Skype',
+    logo: <IconBrandSkype />,
+    connected: false,
+    desc: 'Connect with Skype contacts seamlessly.',
+  },
+  {
+    name: 'Docker',
+    logo: <IconBrandDocker />,
+    connected: false,
+    desc: 'Effortlessly manage Docker containers on your dashboard.',
+  },
+  {
+    name: 'GitHub',
+    logo: <IconBrandGithub />,
+    connected: false,
+    desc: 'Streamline code management with GitHub integration.',
+  },
+  {
+    name: 'GitLab',
+    logo: <IconBrandGitlab />,
+    connected: false,
+    desc: 'Efficiently manage code projects with GitLab integration.',
+  },
+  {
+    name: 'Discord',
+    logo: <IconBrandDiscord />,
+    connected: false,
+    desc: 'Connect with Discord for seamless team communication.',
+  },
+  {
+    name: 'WhatsApp',
+    logo: <IconBrandWhatsapp />,
+    connected: false,
+    desc: 'Easily integrate WhatsApp for direct messaging.',
+  },
+]

+ 145 - 0
src/pages/apps/index.tsx

@@ -0,0 +1,145 @@
+import { useState } from 'react'
+import {
+  IconAdjustmentsHorizontal,
+  IconSortAscendingLetters,
+  IconSortDescendingLetters,
+} from '@tabler/icons-react'
+import { Layout, LayoutBody, LayoutHeader } from '@/components/custom/layout'
+import { Input } from '@/components/ui/input'
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from '@/components/ui/select'
+import { Separator } from '@/components/ui/separator'
+import { Search } from '@/components/search'
+import ThemeSwitch from '@/components/theme-switch'
+import { UserNav } from '@/components/user-nav'
+import { Button } from '@/components/custom/button'
+import { apps } from './data'
+
+const appText = new Map<string, string>([
+  ['all', 'All Apps'],
+  ['connected', 'Connected'],
+  ['notConnected', 'Not Connected'],
+])
+
+export default function Apps() {
+  const [sort, setSort] = useState('ascending')
+  const [appType, setAppType] = useState('all')
+  const [searchTerm, setSearchTerm] = useState('')
+
+  const filteredApps = apps
+    .sort((a, b) =>
+      sort === 'ascending'
+        ? a.name.localeCompare(b.name)
+        : b.name.localeCompare(a.name)
+    )
+    .filter((app) =>
+      appType === 'connected'
+        ? app.connected
+        : appType === 'notConnected'
+          ? !app.connected
+          : true
+    )
+    .filter((app) => app.name.toLowerCase().includes(searchTerm.toLowerCase()))
+
+  return (
+    <Layout fadedBelow fixedHeight>
+      {/* ===== Top Heading ===== */}
+      <LayoutHeader>
+        <div className='flex w-full items-center justify-between'>
+          <Search />
+          <div className='flex items-center space-x-4'>
+            <ThemeSwitch />
+            <UserNav />
+          </div>
+        </div>
+      </LayoutHeader>
+
+      {/* ===== Content ===== */}
+      <LayoutBody className='flex flex-col' fixedHeight>
+        <div>
+          <h1 className='text-2xl font-bold tracking-tight'>
+            App Integrations
+          </h1>
+          <p className='text-muted-foreground'>
+            Here&apos;s a list of your apps for the integration!
+          </p>
+        </div>
+        <div className='my-4 flex items-end justify-between sm:my-0 sm:items-center'>
+          <div className='flex flex-col gap-4 sm:my-4 sm:flex-row'>
+            <Input
+              placeholder='Filter apps...'
+              className='h-9 w-40 lg:w-[250px]'
+              value={searchTerm}
+              onChange={(e) => setSearchTerm(e.target.value)}
+            />
+            <Select value={appType} onValueChange={setAppType}>
+              <SelectTrigger className='w-36'>
+                <SelectValue>{appText.get(appType)}</SelectValue>
+              </SelectTrigger>
+              <SelectContent>
+                <SelectItem value='all'>All Apps</SelectItem>
+                <SelectItem value='connected'>Connected</SelectItem>
+                <SelectItem value='notConnected'>Not Connected</SelectItem>
+              </SelectContent>
+            </Select>
+          </div>
+
+          <Select value={sort} onValueChange={setSort}>
+            <SelectTrigger className='w-16'>
+              <SelectValue>
+                <IconAdjustmentsHorizontal size={18} />
+              </SelectValue>
+            </SelectTrigger>
+            <SelectContent align='end'>
+              <SelectItem value='ascending'>
+                <div className='flex items-center gap-4'>
+                  <IconSortAscendingLetters size={16} />
+                  <span>Ascending</span>
+                </div>
+              </SelectItem>
+              <SelectItem value='descending'>
+                <div className='flex items-center gap-4'>
+                  <IconSortDescendingLetters size={16} />
+                  <span>Descending</span>
+                </div>
+              </SelectItem>
+            </SelectContent>
+          </Select>
+        </div>
+        <Separator className='shadow' />
+        <ul className='no-scrollbar grid gap-4 overflow-y-scroll pb-16 pt-4 md:grid-cols-2 lg:grid-cols-3'>
+          {filteredApps.map((app) => (
+            <li
+              key={app.name}
+              className='rounded-lg border p-4 hover:shadow-md'
+            >
+              <div className='mb-8 flex items-center justify-between'>
+                <div
+                  className={`flex size-10 items-center justify-center rounded-lg bg-muted p-2`}
+                >
+                  {app.logo}
+                </div>
+                <Button
+                  variant='outline'
+                  size='sm'
+                  className={`${app.connected ? 'border border-blue-300 bg-blue-50 hover:bg-blue-100 dark:border-blue-700 dark:bg-blue-950 dark:hover:bg-blue-900' : ''}`}
+                >
+                  {app.connected ? 'Connected' : 'Connect'}
+                </Button>
+              </div>
+              <div>
+                <h2 className='mb-1 font-semibold'>{app.name}</h2>
+                <p className='line-clamp-2 text-gray-500'>{app.desc}</p>
+              </div>
+            </li>
+          ))}
+        </ul>
+      </LayoutBody>
+    </Layout>
+  )
+}

+ 7 - 1
src/router.tsx

@@ -54,7 +54,7 @@ const router = createBrowserRouter([
       {
         path: 'tasks',
         lazy: async () => ({
-          Component: (await import('./pages/tasks')).default,
+          Component: (await import('@/pages/tasks')).default,
         }),
       },
       {
@@ -63,6 +63,12 @@ const router = createBrowserRouter([
           Component: (await import('@/components/coming-soon')).default,
         }),
       },
+      {
+        path: 'apps',
+        lazy: async () => ({
+          Component: (await import('@/pages/apps')).default,
+        }),
+      },
       {
         path: 'users',
         lazy: async () => ({