mirror of
https://github.com/ahmadk953/tasko.git
synced 2025-05-01 03:09:34 +00:00
Formated Files
This commit is contained in:
parent
d5631b309a
commit
e768d9181f
138 changed files with 1829 additions and 1851 deletions
|
@ -1,21 +1,21 @@
|
|||
import Link from "next/link";
|
||||
import { auth } from "@clerk/nextjs";
|
||||
import { redirect } from "next/navigation";
|
||||
import { HelpCircle, User2 } from "lucide-react";
|
||||
import Link from 'next/link';
|
||||
import { auth } from '@clerk/nextjs';
|
||||
import { redirect } from 'next/navigation';
|
||||
import { HelpCircle, User2 } from 'lucide-react';
|
||||
|
||||
import { db } from "@/lib/db";
|
||||
import { Hint } from "@/components/hint";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { FormPopover } from "@/components/form/form-popover";
|
||||
import { MAX_FREE_BOARDS } from "@/constants/boards";
|
||||
import { getAvailableCount } from "@/lib/org-limit";
|
||||
import { checkSubscription } from "@/lib/subscription";
|
||||
import { db } from '@/lib/db';
|
||||
import { Hint } from '@/components/hint';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { FormPopover } from '@/components/form/form-popover';
|
||||
import { MAX_FREE_BOARDS } from '@/constants/boards';
|
||||
import { getAvailableCount } from '@/lib/org-limit';
|
||||
import { checkSubscription } from '@/lib/subscription';
|
||||
|
||||
export const BoardList = async () => {
|
||||
const { orgId } = auth();
|
||||
|
||||
if (!orgId) {
|
||||
return redirect("/select-org");
|
||||
return redirect('/select-org');
|
||||
}
|
||||
|
||||
const boards = await db.board.findMany({
|
||||
|
@ -23,7 +23,7 @@ export const BoardList = async () => {
|
|||
orgId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -31,32 +31,32 @@ export const BoardList = async () => {
|
|||
const isPro = await checkSubscription();
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center font-semibold text-lg text-neutral-700">
|
||||
<User2 className="h-6 w-6 mr-2" />
|
||||
<div className='space-y-4'>
|
||||
<div className='flex items-center text-lg font-semibold text-neutral-700'>
|
||||
<User2 className='mr-2 h-6 w-6' />
|
||||
Your boards
|
||||
</div>
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<div className='grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4'>
|
||||
{boards.map((board) => (
|
||||
<Link
|
||||
key={board.id}
|
||||
href={`/board/${board.id}`}
|
||||
className="group relative aspect-video bg-no-repeat bg-center bg-cover bg-sky-700 rounded-sm h-full w-full p-2 overflow-hidden"
|
||||
className='group relative aspect-video h-full w-full overflow-hidden rounded-sm bg-sky-700 bg-cover bg-center bg-no-repeat p-2'
|
||||
style={{ backgroundImage: `url(${board.imageThumbUrl})` }}
|
||||
>
|
||||
<div className="absolute inset-0 bg-black/30 group-hover:bg-black/40 transition" />
|
||||
<p className="relative font-semibold text-white">{board.title}</p>
|
||||
<div className='absolute inset-0 bg-black/30 transition group-hover:bg-black/40' />
|
||||
<p className='relative font-semibold text-white'>{board.title}</p>
|
||||
</Link>
|
||||
))}
|
||||
<FormPopover sideOffset={10} side="right">
|
||||
<FormPopover sideOffset={10} side='right'>
|
||||
<div
|
||||
role="button"
|
||||
className="aspect-video relative h-full w-full bg-muted rounded-sm flex flex-col gap-y-1 items-center justify-center hover:opacity-75 transition"
|
||||
role='button'
|
||||
className='relative flex aspect-video h-full w-full flex-col items-center justify-center gap-y-1 rounded-sm bg-muted transition hover:opacity-75'
|
||||
>
|
||||
<p className="text-sm">Create new board</p>
|
||||
<span className="text-xs">
|
||||
<p className='text-sm'>Create new board</p>
|
||||
<span className='text-xs'>
|
||||
{isPro
|
||||
? "Unlimited"
|
||||
? 'Unlimited'
|
||||
: `${MAX_FREE_BOARDS - availableCount} remaining`}
|
||||
</span>
|
||||
<Hint
|
||||
|
@ -65,7 +65,7 @@ export const BoardList = async () => {
|
|||
Free Workspaces can have up to 5 open boards. For unlimited boards upgrade this workspace.
|
||||
`}
|
||||
>
|
||||
<HelpCircle className="absolute bottom-2 right-2 h-[14px] w-[14px]" />
|
||||
<HelpCircle className='absolute bottom-2 right-2 h-[14px] w-[14px]' />
|
||||
</Hint>
|
||||
</div>
|
||||
</FormPopover>
|
||||
|
@ -76,15 +76,15 @@ export const BoardList = async () => {
|
|||
|
||||
BoardList.Skeleton = function SkeletonBoardList() {
|
||||
return (
|
||||
<div className="grid gird-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4">
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<Skeleton className="aspect-video h-full w-full p-2" />
|
||||
<div className='gird-cols-2 grid gap-4 sm:grid-cols-3 lg:grid-cols-4'>
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
<Skeleton className='aspect-video h-full w-full p-2' />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
"use client";
|
||||
'use client';
|
||||
|
||||
import Image from "next/image";
|
||||
import { CreditCard } from "lucide-react";
|
||||
import Image from 'next/image';
|
||||
import { CreditCard } from 'lucide-react';
|
||||
|
||||
import { useOrganization } from "@clerk/nextjs";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { useOrganization } from '@clerk/nextjs';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
|
||||
interface InfoProps {
|
||||
isPro: boolean;
|
||||
|
@ -18,20 +18,20 @@ export const Info = ({ isPro }: InfoProps) => {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-x-4">
|
||||
<div className="w-[60px] h-[60px] relative">
|
||||
<div className='flex items-center gap-x-4'>
|
||||
<div className='relative h-[60px] w-[60px]'>
|
||||
<Image
|
||||
fill
|
||||
src={organization?.imageUrl!}
|
||||
alt="Organization Logo"
|
||||
className="rounded-md object-cover"
|
||||
alt='Organization Logo'
|
||||
className='rounded-md object-cover'
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<p className="font-semibold text-xl">{organization?.name}</p>
|
||||
<div className="flex items-center text-xs text-muted-foreground">
|
||||
<CreditCard className="h-3 w-3 mr-1" />
|
||||
{isPro ? "Pro" : "Free"}
|
||||
<div className='space-y-1'>
|
||||
<p className='text-xl font-semibold'>{organization?.name}</p>
|
||||
<div className='flex items-center text-xs text-muted-foreground'>
|
||||
<CreditCard className='mr-1 h-3 w-3' />
|
||||
{isPro ? 'Pro' : 'Free'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -40,15 +40,15 @@ export const Info = ({ isPro }: InfoProps) => {
|
|||
|
||||
Info.Skeleton = function SkeletonInfo() {
|
||||
return (
|
||||
<div className="flex items-center gap-x-4">
|
||||
<div className="w-[60px] h-[60px] relative">
|
||||
<Skeleton className="w-full h-full absolute" />
|
||||
<div className='flex items-center gap-x-4'>
|
||||
<div className='relative h-[60px] w-[60px]'>
|
||||
<Skeleton className='absolute h-full w-full' />
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-10 w-[200px]" />
|
||||
<div className="flex items-center">
|
||||
<Skeleton className="h-4 w-4 mr-2" />
|
||||
<Skeleton className="h-4 w-[100px]" />
|
||||
<div className='space-y-2'>
|
||||
<Skeleton className='h-10 w-[200px]' />
|
||||
<div className='flex items-center'>
|
||||
<Skeleton className='mr-2 h-4 w-4' />
|
||||
<Skeleton className='h-4 w-[100px]' />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
"use client";
|
||||
'use client';
|
||||
|
||||
import { useEffect } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { useOrganizationList } from "@clerk/nextjs";
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useOrganizationList } from '@clerk/nextjs';
|
||||
|
||||
export const OrgControl = () => {
|
||||
const params = useParams();
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import { auth } from "@clerk/nextjs";
|
||||
import { redirect } from "next/navigation";
|
||||
import { auth } from '@clerk/nextjs';
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
import { db } from "@/lib/db";
|
||||
import { ActivityItem } from "@/components/activity-item";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { db } from '@/lib/db';
|
||||
import { ActivityItem } from '@/components/activity-item';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
|
||||
export const ActivityList = async () => {
|
||||
const { orgId } = auth();
|
||||
|
||||
if (!orgId) redirect("/select-org");
|
||||
if (!orgId) redirect('/select-org');
|
||||
|
||||
const auditLogs = await db.auditLog.findMany({
|
||||
where: {
|
||||
orgId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: "desc",
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ol className="space-y-4 mt-4">
|
||||
<p className="hidden last:block text-xs text-center text-muted-foreground">
|
||||
<ol className='mt-4 space-y-4'>
|
||||
<p className='hidden text-center text-xs text-muted-foreground last:block'>
|
||||
No activity found inside this organization
|
||||
</p>
|
||||
{auditLogs.map((log) => (
|
||||
|
@ -33,12 +33,12 @@ export const ActivityList = async () => {
|
|||
|
||||
ActivityList.Skeleton = function ActivityListSkeleton() {
|
||||
return (
|
||||
<ol className="space-y-4 mt-4">
|
||||
<Skeleton className="w-[80%] h-14" />
|
||||
<Skeleton className="w-[50%] h-14" />
|
||||
<Skeleton className="w-[70%] h-14" />
|
||||
<Skeleton className="w-[80%] h-14" />
|
||||
<Skeleton className="w-[75%] h-14" />
|
||||
<ol className='mt-4 space-y-4'>
|
||||
<Skeleton className='h-14 w-[80%]' />
|
||||
<Skeleton className='h-14 w-[50%]' />
|
||||
<Skeleton className='h-14 w-[70%]' />
|
||||
<Skeleton className='h-14 w-[80%]' />
|
||||
<Skeleton className='h-14 w-[75%]' />
|
||||
</ol>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { Suspense } from "react";
|
||||
import { Suspense } from 'react';
|
||||
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
|
||||
import { Info } from "../_components/info";
|
||||
import { ActivityList } from "./_components/activity-list";
|
||||
import { checkSubscription } from "@/lib/subscription";
|
||||
import { Info } from '../_components/info';
|
||||
import { ActivityList } from './_components/activity-list';
|
||||
import { checkSubscription } from '@/lib/subscription';
|
||||
|
||||
const ActivityPage = async () => {
|
||||
const isPro = await checkSubscription();
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className='w-full'>
|
||||
<Info isPro={isPro} />
|
||||
<Separator className="my-2" />
|
||||
<Separator className='my-2' />
|
||||
<Suspense fallback={<ActivityList.Skeleton />}>
|
||||
<ActivityList />
|
||||
</Suspense>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
"use client";
|
||||
'use client';
|
||||
|
||||
import { toast } from "sonner";
|
||||
import { toast } from 'sonner';
|
||||
|
||||
import { stripeRedirect } from "@/actions/stripe-redirect";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useAction } from "@/hooks/use-action";
|
||||
import { useProModal } from "@/hooks/use-pro-modal";
|
||||
import { stripeRedirect } from '@/actions/stripe-redirect';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useAction } from '@/hooks/use-action';
|
||||
import { useProModal } from '@/hooks/use-pro-modal';
|
||||
|
||||
interface SubscriptionButtonProps {
|
||||
isPro: boolean;
|
||||
|
@ -32,8 +32,8 @@ export const SubscriptionButton = ({ isPro }: SubscriptionButtonProps) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Button disabled={isLoading} onClick={onClick} variant="primary">
|
||||
{isPro ? "Manage Subscription" : "Upgrade to Pro"}
|
||||
<Button disabled={isLoading} onClick={onClick} variant='primary'>
|
||||
{isPro ? 'Manage Subscription' : 'Upgrade to Pro'}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { checkSubscription } from "@/lib/subscription";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { checkSubscription } from '@/lib/subscription';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
|
||||
import { Info } from "../_components/info";
|
||||
import { SubscriptionButton } from "./_components/subscription-button";
|
||||
import { Info } from '../_components/info';
|
||||
import { SubscriptionButton } from './_components/subscription-button';
|
||||
|
||||
const BillingPage = async () => {
|
||||
const isPro = await checkSubscription();
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className='w-full'>
|
||||
<Info isPro={isPro} />
|
||||
<Separator className="my-2" />
|
||||
<Separator className='my-2' />
|
||||
<SubscriptionButton isPro={isPro} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BillingPage;
|
||||
export default BillingPage;
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { startCase } from "lodash";
|
||||
import { auth } from "@clerk/nextjs";
|
||||
import { startCase } from 'lodash';
|
||||
import { auth } from '@clerk/nextjs';
|
||||
|
||||
import { OrgControl } from "./_components/org-control";
|
||||
import { OrgControl } from './_components/org-control';
|
||||
|
||||
export async function generateMetadata() {
|
||||
const { orgSlug } = auth();
|
||||
|
||||
return {
|
||||
title: startCase(orgSlug ?? "organization"),
|
||||
title: startCase(orgSlug ?? 'organization'),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { Suspense } from "react";
|
||||
import { Suspense } from 'react';
|
||||
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { checkSubscription } from "@/lib/subscription";
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { checkSubscription } from '@/lib/subscription';
|
||||
|
||||
import { Info } from "./_components/info";
|
||||
import { BoardList } from "./_components/board-list";
|
||||
import { Info } from './_components/info';
|
||||
import { BoardList } from './_components/board-list';
|
||||
|
||||
const OrganizationIdPage = async () => {
|
||||
const isPro = await checkSubscription();
|
||||
|
||||
return (
|
||||
<div className="w-full mb-20">
|
||||
<div className='mb-20 w-full'>
|
||||
<Info isPro={isPro} />
|
||||
<Separator className="my-4" />
|
||||
<div className="px-2 md:px-4">
|
||||
<Separator className='my-4' />
|
||||
<div className='px-2 md:px-4'>
|
||||
<Suspense fallback={<BoardList.Skeleton />}>
|
||||
<BoardList />
|
||||
</Suspense>
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import { OrganizationProfile } from "@clerk/nextjs";
|
||||
import { OrganizationProfile } from '@clerk/nextjs';
|
||||
|
||||
const SettingsPage = () => {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className='w-full'>
|
||||
<OrganizationProfile
|
||||
appearance={{
|
||||
elements: {
|
||||
rootBox: {
|
||||
boxShadow: "none",
|
||||
width: "100%",
|
||||
boxShadow: 'none',
|
||||
width: '100%',
|
||||
},
|
||||
card: {
|
||||
border: "1px solid #e5e5e5",
|
||||
boxShadow: "none",
|
||||
width: "100%",
|
||||
border: '1px solid #e5e5e5',
|
||||
boxShadow: 'none',
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Sidebar } from "../_components/sidebar";
|
||||
import { Sidebar } from '../_components/sidebar';
|
||||
|
||||
const OrganizationLayout = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
<main className="pt-20 md:pt-24 px-4 max-w-6xl 2xl:max-w-screen-xl mx-auto">
|
||||
<div className="flex gap-x-7">
|
||||
<div className="w-64 shrink-0 hidden md:block">
|
||||
<main className='mx-auto max-w-6xl px-4 pt-20 md:pt-24 2xl:max-w-screen-xl'>
|
||||
<div className='flex gap-x-7'>
|
||||
<div className='hidden w-64 shrink-0 md:block'>
|
||||
<Sidebar />
|
||||
</div>
|
||||
{children}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue