mirror of
https://github.com/chartdb/chartdb.git
synced 2025-10-23 07:11:56 +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">
|
||||
<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>
|
||||
{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