ui: replace custom loading spinners with IconSpinner component across multiple files
This commit is contained in:
@@ -16,6 +16,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
IconSpinner,
|
||||
Input,
|
||||
} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
@@ -33,16 +34,6 @@ import {useProjects} from '../../lib/hooks/useProject';
|
||||
import {useUser} from '../../lib/hooks/useUser';
|
||||
import {network} from '../../lib/network';
|
||||
|
||||
const Spinner = () => (
|
||||
<svg className="h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default function Login() {
|
||||
const {mutate: userMutate} = useUser();
|
||||
@@ -296,7 +287,7 @@ export default function Login() {
|
||||
<Button type="submit" className="w-full" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting ? (
|
||||
<>
|
||||
<Spinner />
|
||||
<IconSpinner size="sm" />
|
||||
Signing in...
|
||||
</>
|
||||
) : (
|
||||
@@ -352,7 +343,7 @@ export default function Login() {
|
||||
<Button className="w-full" type="submit" disabled={resetStatus === 'loading'}>
|
||||
{resetStatus === 'loading' ? (
|
||||
<>
|
||||
<Spinner />
|
||||
<IconSpinner size="sm" />
|
||||
Sending...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
IconSpinner,
|
||||
Input,
|
||||
} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
@@ -29,16 +30,6 @@ const dotGrid = {
|
||||
backgroundSize: '20px 20px',
|
||||
};
|
||||
|
||||
const Spinner = () => (
|
||||
<svg className="h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
const Wordmark = () => (
|
||||
<div className="flex items-center justify-center gap-2.5">
|
||||
@@ -202,7 +193,7 @@ export default function ResetPassword() {
|
||||
<Button type="submit" className="w-full" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting ? (
|
||||
<>
|
||||
<Spinner />
|
||||
<IconSpinner size="sm" />
|
||||
Resetting...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
IconSpinner,
|
||||
Input,
|
||||
} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
@@ -27,16 +28,6 @@ import {useProjects} from '../../lib/hooks/useProject';
|
||||
import {useUser} from '../../lib/hooks/useUser';
|
||||
import {network} from '../../lib/network';
|
||||
|
||||
const Spinner = () => (
|
||||
<svg className="h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default function Signup() {
|
||||
const {mutate: userMutate} = useUser();
|
||||
@@ -226,7 +217,7 @@ export default function Signup() {
|
||||
<Button type="submit" className="w-full" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting ? (
|
||||
<>
|
||||
<Spinner />
|
||||
<IconSpinner size="sm" />
|
||||
Creating account...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {AuthenticationSchemas} from '@plunk/shared';
|
||||
import {Button, Card, CardContent} from '@plunk/ui';
|
||||
import {Button, Card, CardContent, IconSpinner} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {NextSeo} from 'next-seo';
|
||||
import Image from 'next/image';
|
||||
@@ -15,16 +15,6 @@ const dotGrid = {
|
||||
backgroundSize: '20px 20px',
|
||||
};
|
||||
|
||||
const Spinner = () => (
|
||||
<svg className="h-6 w-6 animate-spin text-neutral-500" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default function VerifyEmail() {
|
||||
const router = useRouter();
|
||||
@@ -219,7 +209,7 @@ export default function VerifyEmail() {
|
||||
className="flex flex-col items-center gap-4"
|
||||
>
|
||||
<div className="h-12 w-12 rounded-full bg-neutral-100 flex items-center justify-center">
|
||||
<Spinner />
|
||||
<IconSpinner size="sm" />
|
||||
</div>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<h1 className="text-xl font-bold tracking-tight">Verifying...</h1>
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
SelectItemWithDescription,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
IconSpinner,
|
||||
StickySaveBar,
|
||||
} from '@plunk/ui';
|
||||
import type {Campaign, Segment} from '@plunk/db';
|
||||
@@ -308,10 +309,7 @@ export default function CampaignDetailsPage() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<div className="h-8 w-8 animate-spin mx-auto border-4 border-neutral-200 border-t-neutral-900 rounded-full" />
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading campaign...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
@@ -166,21 +167,9 @@ export default function CreateCampaignPage() {
|
||||
<NextSeo title="Create Campaign" />
|
||||
<DashboardLayout>
|
||||
{loadingTemplate && (
|
||||
<div className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center">
|
||||
<div className="bg-white rounded-lg p-6 text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900 mb-3"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<div className="fixed inset-0 bg-black/40 z-50 flex items-center justify-center">
|
||||
<div className="bg-white rounded-lg p-5 flex items-center gap-3">
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-700">Loading template...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,13 +5,14 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
ConfirmDialog,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
Switch,
|
||||
} from '@plunk/ui';
|
||||
import type {Contact} from '@plunk/db';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {ArrowLeft, Check, Copy, Database, ExternalLink, Loader2, Save, Settings, Trash2} from 'lucide-react';
|
||||
import {ArrowLeft, Check, Copy, Database, ExternalLink, Save, Settings, Trash2} from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import {NextSeo} from 'next-seo';
|
||||
import {useRouter} from 'next/router';
|
||||
@@ -90,7 +91,7 @@ export default function ContactDetailPage() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<Loader2 className="h-8 w-8 animate-spin text-neutral-400" />
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
Switch,
|
||||
@@ -265,22 +266,7 @@ export default function ContactsPage() {
|
||||
<CardContent>
|
||||
{isLoading && contacts.length === 0 ? (
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading contacts...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
) : contacts.length === 0 ? (
|
||||
<EmptyState
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button, Card, CardContent} from '@plunk/ui';
|
||||
import {Button, Card, CardContent, IconSpinner} from '@plunk/ui';
|
||||
import {createTranslator, type Translator} from '@plunk/shared';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {useRouter} from 'next/router';
|
||||
@@ -82,19 +82,7 @@ export default function Manage() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">Loading...</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -111,19 +99,7 @@ export default function Manage() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">{translator.t('pages.common.loading')}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
IconSpinner,
|
||||
Input,
|
||||
} from '@plunk/ui';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
@@ -129,26 +130,7 @@ export default function CreateProject() {
|
||||
<Button type="submit" className="w-full" disabled={form.formState.isSubmitting}>
|
||||
{form.formState.isSubmitting ? (
|
||||
<>
|
||||
<svg
|
||||
className="h-4 w-4 animate-spin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
/>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner size="sm" className="mr-2" />
|
||||
Creating...
|
||||
</>
|
||||
) : (
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
ConfirmDialog,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
} from '@plunk/ui';
|
||||
@@ -178,22 +179,7 @@ export default function SegmentDetailPage() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading segment...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
ConfirmDialog,
|
||||
IconSpinner,
|
||||
} from '@plunk/ui';
|
||||
import type {Segment} from '@plunk/db';
|
||||
import type {FilterCondition} from '@plunk/types';
|
||||
@@ -105,22 +106,7 @@ export default function SegmentsPage() {
|
||||
{/* Segments Grid */}
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading segments...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
) : segments?.length === 0 ? (
|
||||
<Card>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button, Card, CardContent} from '@plunk/ui';
|
||||
import {Button, Card, CardContent, IconSpinner} from '@plunk/ui';
|
||||
import {createTranslator, type Translator} from '@plunk/shared';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {useRouter} from 'next/router';
|
||||
@@ -72,19 +72,7 @@ export default function Subscribe() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">Loading...</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -101,19 +89,7 @@ export default function Subscribe() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">{translator.t('pages.common.loading')}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -219,19 +195,7 @@ export default function Subscribe() {
|
||||
<Button onClick={() => void handleSubscribe()} className="w-full" disabled={subscribing}>
|
||||
{subscribing ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<svg
|
||||
className="h-4 w-4 animate-spin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner size="sm" />
|
||||
<span>{translator.t('pages.subscribe.buttonLoading')}</span>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
ConfirmDialog,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
StickySaveBar,
|
||||
@@ -117,22 +118,7 @@ export default function TemplateEditorPage() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<div className="flex items-center justify-center min-h-[400px]">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading template...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
ConfirmDialog,
|
||||
IconSpinner,
|
||||
Input,
|
||||
} from '@plunk/ui';
|
||||
import type {Template} from '@plunk/db';
|
||||
@@ -165,22 +166,7 @@ export default function TemplatesPage() {
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading templates...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {Button, Card, CardContent} from '@plunk/ui';
|
||||
import {Button, Card, CardContent, IconSpinner} from '@plunk/ui';
|
||||
import {createTranslator, type Translator} from '@plunk/shared';
|
||||
import {AnimatePresence, motion} from 'framer-motion';
|
||||
import {useRouter} from 'next/router';
|
||||
@@ -72,19 +72,7 @@ export default function Unsubscribe() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">Loading...</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -101,19 +89,7 @@ export default function Unsubscribe() {
|
||||
<Card>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin text-neutral-500"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner />
|
||||
<p className="text-sm text-neutral-500">{translator.t('pages.common.loading')}</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
@@ -236,19 +212,7 @@ export default function Unsubscribe() {
|
||||
>
|
||||
{unsubscribing ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<svg
|
||||
className="h-4 w-4 animate-spin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner size="sm" />
|
||||
<span>{translator.t('pages.unsubscribe.buttonLoading')}</span>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
CommandGroup,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
IconSpinner,
|
||||
Switch,
|
||||
} from '@plunk/ui';
|
||||
import type {Template, Workflow, WorkflowExecution, WorkflowStep, WorkflowTransition} from '@plunk/db';
|
||||
@@ -406,22 +407,7 @@ export default function WorkflowEditorPage() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<div className="flex items-center justify-center min-h-[400px]">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading workflow...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</DashboardLayout>
|
||||
);
|
||||
@@ -1463,19 +1449,7 @@ function AddStepDialog({open, onOpenChange, workflowId, onSuccess}: AddStepDialo
|
||||
</Label>
|
||||
{loadingFields ? (
|
||||
<div className="flex items-center gap-2 px-3 py-2 border border-neutral-200 rounded-lg text-sm text-neutral-500 mt-1.5">
|
||||
<svg
|
||||
className="h-4 w-4 animate-spin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner size="sm" />
|
||||
Loading fields...
|
||||
</div>
|
||||
) : availableFields.length > 0 ? (
|
||||
@@ -2520,19 +2494,7 @@ function EditStepDialog({step, workflowId, open, onOpenChange, onSuccess}: EditS
|
||||
<Label htmlFor="editConditionField">Field to Check *</Label>
|
||||
{loadingFields ? (
|
||||
<div className="flex items-center gap-2 px-3 py-2 border border-neutral-200 rounded-lg text-sm text-neutral-500 mt-1.5">
|
||||
<svg
|
||||
className="h-4 w-4 animate-spin"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<IconSpinner size="sm" />
|
||||
Loading fields...
|
||||
</div>
|
||||
) : availableFields.length > 0 ? (
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
IconSpinner,
|
||||
Input,
|
||||
Label,
|
||||
} from '@plunk/ui';
|
||||
@@ -137,22 +138,7 @@ export default function WorkflowsPage() {
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<svg
|
||||
className="h-8 w-8 animate-spin mx-auto text-neutral-900"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
<p className="mt-2 text-sm text-neutral-500">Loading workflows...</p>
|
||||
</div>
|
||||
<IconSpinner />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user