mirror of
				https://github.com/chartdb/chartdb.git
				synced 2025-11-03 21:43:23 +00:00 
			
		
		
		
	fix(examples): add loader (#678)
This commit is contained in:
		@@ -1,4 +1,4 @@
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
import React, { useRef } from 'react';
 | 
			
		||||
import type { Example } from './examples-data/examples-data';
 | 
			
		||||
import { randomColor } from '@/lib/colors';
 | 
			
		||||
import { Import } from 'lucide-react';
 | 
			
		||||
@@ -13,35 +13,23 @@ import {
 | 
			
		||||
    TooltipContent,
 | 
			
		||||
    TooltipTrigger,
 | 
			
		||||
} from '@/components/tooltip/tooltip';
 | 
			
		||||
import { useStorage } from '@/hooks/use-storage';
 | 
			
		||||
import type { Diagram } from '@/lib/domain/diagram';
 | 
			
		||||
import { useNavigate } from 'react-router-dom';
 | 
			
		||||
import { useTheme } from '@/hooks/use-theme';
 | 
			
		||||
import { Spinner } from '@/components/spinner/spinner';
 | 
			
		||||
 | 
			
		||||
export interface ExampleCardProps {
 | 
			
		||||
    example: Example;
 | 
			
		||||
    utilizeExample: () => void;
 | 
			
		||||
    loading: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const ExampleCard: React.FC<ExampleCardProps> = ({ example }) => {
 | 
			
		||||
    const navigate = useNavigate();
 | 
			
		||||
export const ExampleCard: React.FC<ExampleCardProps> = ({
 | 
			
		||||
    example,
 | 
			
		||||
    utilizeExample,
 | 
			
		||||
    loading,
 | 
			
		||||
}) => {
 | 
			
		||||
    const { effectiveTheme } = useTheme();
 | 
			
		||||
    const { addDiagram, deleteDiagram } = useStorage();
 | 
			
		||||
    const { diagram } = example;
 | 
			
		||||
    const utilizeExample = useCallback(async () => {
 | 
			
		||||
        const { id } = diagram;
 | 
			
		||||
    const color = useRef(randomColor());
 | 
			
		||||
 | 
			
		||||
        await deleteDiagram(id);
 | 
			
		||||
 | 
			
		||||
        const now = new Date();
 | 
			
		||||
        const diagramToAdd: Diagram = {
 | 
			
		||||
            ...diagram,
 | 
			
		||||
            createdAt: now,
 | 
			
		||||
            updatedAt: now,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        await addDiagram({ diagram: diagramToAdd });
 | 
			
		||||
        navigate(`/diagrams/${id}`);
 | 
			
		||||
    }, [addDiagram, diagram, navigate, deleteDiagram]);
 | 
			
		||||
    return (
 | 
			
		||||
        <div
 | 
			
		||||
            onClick={utilizeExample}
 | 
			
		||||
@@ -49,7 +37,7 @@ export const ExampleCard: React.FC<ExampleCardProps> = ({ example }) => {
 | 
			
		||||
        >
 | 
			
		||||
            <div
 | 
			
		||||
                className="h-4 rounded-t-[10px]"
 | 
			
		||||
                style={{ backgroundColor: randomColor() }}
 | 
			
		||||
                style={{ backgroundColor: color.current }}
 | 
			
		||||
            ></div>
 | 
			
		||||
            <div className="flex h-12 items-center justify-between bg-slate-200 px-2 dark:bg-slate-900">
 | 
			
		||||
                <div className="flex items-center gap-2">
 | 
			
		||||
@@ -78,12 +66,16 @@ export const ExampleCard: React.FC<ExampleCardProps> = ({ example }) => {
 | 
			
		||||
                    </Label>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className="flex flex-row">
 | 
			
		||||
                    {loading ? (
 | 
			
		||||
                        <Spinner className="size-5" />
 | 
			
		||||
                    ) : (
 | 
			
		||||
                        <Button
 | 
			
		||||
                            variant="ghost"
 | 
			
		||||
                            className="size-9 p-0 text-slate-500 hover:bg-primary-foreground hover:text-slate-700 dark:text-slate-400 dark:hover:bg-slate-800 dark:hover:text-slate-200"
 | 
			
		||||
                        >
 | 
			
		||||
                            <Import className="size-5" />
 | 
			
		||||
                        </Button>
 | 
			
		||||
                    )}
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className="grow overflow-hidden">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
import ChartDBLogo from '@/assets/logo-light.png';
 | 
			
		||||
import ChartDBDarkLogo from '@/assets/logo-dark.png';
 | 
			
		||||
import type { Example } from './examples-data/examples-data';
 | 
			
		||||
import { examples } from './examples-data/examples-data';
 | 
			
		||||
import { ExampleCard } from './example-card';
 | 
			
		||||
import { useTheme } from '@/hooks/use-theme';
 | 
			
		||||
@@ -8,9 +9,44 @@ import { LocalConfigProvider } from '@/context/local-config-context/local-config
 | 
			
		||||
import { StorageProvider } from '@/context/storage-context/storage-provider';
 | 
			
		||||
import { ThemeProvider } from '@/context/theme-context/theme-provider';
 | 
			
		||||
import { Helmet } from 'react-helmet-async';
 | 
			
		||||
import { useNavigate } from 'react-router-dom';
 | 
			
		||||
import { useStorage } from '@/hooks/use-storage';
 | 
			
		||||
import type { Diagram } from '@/lib/domain/diagram';
 | 
			
		||||
 | 
			
		||||
const ExamplesPageComponent: React.FC = () => {
 | 
			
		||||
    const { effectiveTheme } = useTheme();
 | 
			
		||||
    const navigate = useNavigate();
 | 
			
		||||
    const { addDiagram, deleteDiagram } = useStorage();
 | 
			
		||||
    const [loadingExampleId, setLoadingExampleId] = React.useState<string>();
 | 
			
		||||
    const utilizeExample = useCallback(
 | 
			
		||||
        async ({ example }: { example: Example }) => {
 | 
			
		||||
            if (loadingExampleId) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            setLoadingExampleId(example.id);
 | 
			
		||||
            const { diagram } = example;
 | 
			
		||||
            const { id } = diagram;
 | 
			
		||||
 | 
			
		||||
            await deleteDiagram(id);
 | 
			
		||||
 | 
			
		||||
            const now = new Date();
 | 
			
		||||
            const diagramToAdd: Diagram = {
 | 
			
		||||
                ...diagram,
 | 
			
		||||
                createdAt: now,
 | 
			
		||||
                updatedAt: now,
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            await addDiagram({ diagram: diagramToAdd });
 | 
			
		||||
            navigate(`/diagrams/${id}`);
 | 
			
		||||
        },
 | 
			
		||||
        [
 | 
			
		||||
            addDiagram,
 | 
			
		||||
            navigate,
 | 
			
		||||
            deleteDiagram,
 | 
			
		||||
            loadingExampleId,
 | 
			
		||||
            setLoadingExampleId,
 | 
			
		||||
        ]
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
@@ -54,7 +90,14 @@ const ExamplesPageComponent: React.FC = () => {
 | 
			
		||||
                    </h2>
 | 
			
		||||
                    <div className="mt-6 grid grid-flow-row grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
 | 
			
		||||
                        {examples.map((example) => (
 | 
			
		||||
                            <ExampleCard key={example.id} example={example} />
 | 
			
		||||
                            <ExampleCard
 | 
			
		||||
                                key={example.id}
 | 
			
		||||
                                example={example}
 | 
			
		||||
                                utilizeExample={() =>
 | 
			
		||||
                                    utilizeExample({ example })
 | 
			
		||||
                                }
 | 
			
		||||
                                loading={loadingExampleId === example.id}
 | 
			
		||||
                            />
 | 
			
		||||
                        ))}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user