Added skeleton when loading all flows

This commit is contained in:
Lucas Oliveira 2023-08-30 22:56:43 -03:00
commit ee27839009
6 changed files with 101 additions and 29 deletions

View file

@ -0,0 +1,16 @@
import { Skeleton } from "../ui/skeleton";
export const SkeletonCardComponent = (): JSX.Element => {
return (
<div className="skeleton-card">
<div className="skeleton-card-wrapper">
<Skeleton className="h-8 w-8 rounded-full" />
<Skeleton className="h-4 w-[120px]" />
</div>
<div className="skeleton-card-text">
<Skeleton className="h-3 w-[250px]" />
<Skeleton className="h-3 w-[200px]" />
</div>
</div>
);
};

View file

@ -0,0 +1,15 @@
import { cn } from "../../utils/utils"
function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={cn("animate-pulse rounded-md bg-border", className)}
{...props}
/>
)
}
export { Skeleton }

View file

@ -39,6 +39,7 @@ const TabsContextInitialValue: TabsContextType = {
save: () => {}, save: () => {},
tabId: "", tabId: "",
setTabId: (index: string) => {}, setTabId: (index: string) => {},
isLoading: true,
flows: [], flows: [],
removeFlow: (id: string) => {}, removeFlow: (id: string) => {},
addFlow: async (flowData?: any) => "", addFlow: async (flowData?: any) => "",
@ -76,6 +77,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
const [tabId, setTabId] = useState(""); const [tabId, setTabId] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [flows, setFlows] = useState<Array<FlowType>>([]); const [flows, setFlows] = useState<Array<FlowType>>([]);
const [id, setId] = useState(uid()); const [id, setId] = useState(uid());
const { templates, reactFlowInstance } = useContext(typesContext); const { templates, reactFlowInstance } = useContext(typesContext);
@ -90,7 +93,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
if (!isAuthenticated) { if (!isAuthenticated) {
hardReset(); hardReset();
} }
}, [isAuthenticated]) }, [isAuthenticated]);
const newNodeId = useRef(uid()); const newNodeId = useRef(uid());
function incrementNodeId() { function incrementNodeId() {
@ -122,11 +125,13 @@ export function TabsProvider({ children }: { children: ReactNode }) {
} }
function refreshFlows() { function refreshFlows() {
setIsLoading(true);
getTabsDataFromDB().then((DbData) => { getTabsDataFromDB().then((DbData) => {
if (DbData && Object.keys(templates).length > 0) { if (DbData && Object.keys(templates).length > 0) {
try { try {
processDBData(DbData); processDBData(DbData);
updateStateWithDbData(DbData); updateStateWithDbData(DbData);
setIsLoading(false);
} catch (e) {} } catch (e) {}
} }
}); });
@ -235,6 +240,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
setTabId(""); setTabId("");
setFlows([]); setFlows([]);
setIsLoading(true);
setId(uid()); setId(uid());
} }
@ -647,6 +653,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
paste, paste,
getTweak, getTweak,
setTweak, setTweak,
isLoading,
}} }}
> >
{children} {children}

View file

@ -3,12 +3,20 @@ import { Link, useNavigate } from "react-router-dom";
import { CardComponent } from "../../components/cardComponent"; import { CardComponent } from "../../components/cardComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import Header from "../../components/headerComponent"; import Header from "../../components/headerComponent";
import { SkeletonCardComponent } from "../../components/skeletonCardComponent";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { USER_PROJECTS_HEADER } from "../../constants/constants"; import { USER_PROJECTS_HEADER } from "../../constants/constants";
import { TabsContext } from "../../contexts/tabsContext"; import { TabsContext } from "../../contexts/tabsContext";
export default function HomePage(): JSX.Element { export default function HomePage(): JSX.Element {
const { flows, setTabId, downloadFlows, uploadFlows, addFlow, removeFlow } = const {
useContext(TabsContext); flows,
setTabId,
downloadFlows,
uploadFlows,
addFlow,
removeFlow,
isLoading,
} = useContext(TabsContext);
// Set a null id // Set a null id
useEffect(() => { useEffect(() => {
@ -16,6 +24,10 @@ export default function HomePage(): JSX.Element {
}, []); }, []);
const navigate = useNavigate(); const navigate = useNavigate();
useEffect(() => {
console.log(isLoading);
}, [isLoading]);
// Personal flows display // Personal flows display
return ( return (
<> <>
@ -62,7 +74,15 @@ export default function HomePage(): JSX.Element {
Manage your personal projects. Download or upload your collection. Manage your personal projects. Download or upload your collection.
</span> </span>
<div className="main-page-flows-display"> <div className="main-page-flows-display">
{flows.map((flow, idx) => ( {isLoading && flows.length == 0 ? (
<>
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
<SkeletonCardComponent />
</>
) : (
flows.map((flow, idx) => (
<CardComponent <CardComponent
key={idx} key={idx}
flow={flow} flow={flow}
@ -86,7 +106,8 @@ export default function HomePage(): JSX.Element {
removeFlow(flow.id); removeFlow(flow.id);
}} }}
/> />
))} ))
)}
</div> </div>
</div> </div>
</> </>

View file

@ -126,6 +126,18 @@
@apply form-input block w-full truncate rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm; @apply form-input block w-full truncate rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm;
} }
.skeleton-card {
@apply bg-background h-48 p-4 border rounded-lg flex flex-col gap-6;
}
.skeleton-card-wrapper {
@apply flex items-center space-x-4;
}
.skeleton-card-text {
@apply flex flex-col gap-3;
}
/* The same as primary-input but no-truncate */ /* The same as primary-input but no-truncate */
.textarea-primary { .textarea-primary {
@apply form-input block w-full rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm; @apply form-input block w-full rounded-md border-border bg-background px-3 text-left shadow-sm placeholder:text-muted-foreground focus:border-ring focus:placeholder-transparent focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 sm:text-sm;

View file

@ -5,6 +5,7 @@ export type TabsContextType = {
saveFlow: (flow: FlowType) => Promise<void>; saveFlow: (flow: FlowType) => Promise<void>;
save: () => void; save: () => void;
tabId: string; tabId: string;
isLoading: boolean;
setTabId: (index: string) => void; setTabId: (index: string) => void;
flows: Array<FlowType>; flows: Array<FlowType>;
removeFlow: (id: string) => void; removeFlow: (id: string) => void;