Shadcn conversion, lots of styling
This commit is contained in:
@@ -1,60 +0,0 @@
|
|||||||
import { Button } from "@/components/ui/button"
|
|
||||||
import { X } from "lucide-react"
|
|
||||||
import {
|
|
||||||
AlertDialog,
|
|
||||||
AlertDialogAction,
|
|
||||||
AlertDialogCancel,
|
|
||||||
AlertDialogContent,
|
|
||||||
AlertDialogDescription,
|
|
||||||
AlertDialogFooter,
|
|
||||||
AlertDialogHeader,
|
|
||||||
AlertDialogTitle,
|
|
||||||
AlertDialogTrigger,
|
|
||||||
AlertDialogPortal,
|
|
||||||
AlertDialogOverlay,
|
|
||||||
} from "@/components/ui/alert-dialog"
|
|
||||||
import { useRsi } from "../hooks/useRsi"
|
|
||||||
|
|
||||||
type ModalCloseButtonProps = {
|
|
||||||
onClose: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ModalCloseButton = ({ onClose }: ModalCloseButtonProps) => {
|
|
||||||
const { translations } = useRsi()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AlertDialog>
|
|
||||||
<AlertDialogTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className="absolute right-4 top-4 z-[60] h-10 w-10 rounded-full bg-background/80 p-0 text-muted-foreground backdrop-blur-sm hover:bg-background/50"
|
|
||||||
>
|
|
||||||
<X className="h-5 w-5" />
|
|
||||||
<span className="sr-only">Close modal</span>
|
|
||||||
</Button>
|
|
||||||
</AlertDialogTrigger>
|
|
||||||
<AlertDialogPortal>
|
|
||||||
<AlertDialogOverlay className="z-[1400]" />
|
|
||||||
<AlertDialogContent className="z-[1500]">
|
|
||||||
<AlertDialogHeader>
|
|
||||||
<AlertDialogTitle>
|
|
||||||
{translations.alerts.confirmClose.headerTitle}
|
|
||||||
</AlertDialogTitle>
|
|
||||||
<AlertDialogDescription>
|
|
||||||
{translations.alerts.confirmClose.bodyText}
|
|
||||||
</AlertDialogDescription>
|
|
||||||
</AlertDialogHeader>
|
|
||||||
<AlertDialogFooter>
|
|
||||||
<AlertDialogCancel>
|
|
||||||
{translations.alerts.confirmClose.cancelButtonTitle}
|
|
||||||
</AlertDialogCancel>
|
|
||||||
<AlertDialogAction onClick={onClose}>
|
|
||||||
{translations.alerts.confirmClose.exitButtonTitle}
|
|
||||||
</AlertDialogAction>
|
|
||||||
</AlertDialogFooter>
|
|
||||||
</AlertDialogContent>
|
|
||||||
</AlertDialogPortal>
|
|
||||||
</AlertDialog>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,26 @@
|
|||||||
import type React from "react"
|
import type React from "react"
|
||||||
import { Modal, ModalContent, ModalOverlay } from "@chakra-ui/react"
|
import {
|
||||||
import { ModalCloseButton } from "./ModalCloseButton"
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogOverlay,
|
||||||
|
DialogPortal,
|
||||||
|
DialogClose,
|
||||||
|
} from "@/components/ui/dialog"
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogAction,
|
||||||
|
AlertDialogCancel,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogDescription,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogTitle,
|
||||||
|
AlertDialogTrigger,
|
||||||
|
AlertDialogPortal,
|
||||||
|
AlertDialogOverlay,
|
||||||
|
} from "@/components/ui/alert-dialog"
|
||||||
import { useRsi } from "../hooks/useRsi"
|
import { useRsi } from "../hooks/useRsi"
|
||||||
|
import { useState } from "react"
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
@@ -10,24 +29,60 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ModalWrapper = ({ children, isOpen, onClose }: Props) => {
|
export const ModalWrapper = ({ children, isOpen, onClose }: Props) => {
|
||||||
const { rtl } = useRsi()
|
const { rtl, translations } = useRsi()
|
||||||
|
const [showCloseAlert, setShowCloseAlert] = useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<>
|
||||||
isOpen={isOpen}
|
<Dialog open={isOpen} onOpenChange={() => setShowCloseAlert(true)} modal>
|
||||||
onClose={onClose}
|
<DialogPortal>
|
||||||
id="rsi"
|
<DialogOverlay className="bg-background/80 backdrop-blur-sm" />
|
||||||
variant="rsi"
|
<DialogContent
|
||||||
closeOnEsc={false}
|
onEscapeKeyDown={(e) => {
|
||||||
closeOnOverlayClick={false}
|
e.preventDefault()
|
||||||
scrollBehavior="inside"
|
setShowCloseAlert(true)
|
||||||
|
}}
|
||||||
|
onPointerDownOutside={(e) => e.preventDefault()}
|
||||||
|
className="fixed left-[50%] top-[50%] translate-x-[-50%] translate-y-[-50%] w-[calc(100%-2rem)] h-[calc(100%-2rem)] max-w-[100vw] max-h-[100vh] flex flex-col overflow-hidden rounded-lg border bg-background p-0 shadow-lg sm:w-[calc(100%-3rem)] sm:h-[calc(100%-3rem)] md:w-[calc(100%-4rem)] md:h-[calc(100%-4rem)]"
|
||||||
>
|
>
|
||||||
<ModalOverlay />
|
<AlertDialog>
|
||||||
<ModalContent>
|
<AlertDialogTrigger asChild>
|
||||||
<div dir={rtl ? "rtl" : "ltr"} className="relative">
|
<DialogClose className="absolute right-4 top-4" onClick={(e) => {
|
||||||
<ModalCloseButton onClose={onClose} />
|
e.preventDefault()
|
||||||
|
setShowCloseAlert(true)
|
||||||
|
}} />
|
||||||
|
</AlertDialogTrigger>
|
||||||
|
</AlertDialog>
|
||||||
|
<div dir={rtl ? "rtl" : "ltr"} className="flex-1 overflow-auto">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</ModalContent>
|
</DialogContent>
|
||||||
</Modal>
|
</DialogPortal>
|
||||||
|
</Dialog>
|
||||||
|
|
||||||
|
<AlertDialog open={showCloseAlert} onOpenChange={setShowCloseAlert}>
|
||||||
|
<AlertDialogPortal>
|
||||||
|
<AlertDialogOverlay className="z-[1400]" />
|
||||||
|
<AlertDialogContent className="z-[1500]">
|
||||||
|
<AlertDialogHeader>
|
||||||
|
<AlertDialogTitle>
|
||||||
|
{translations.alerts.confirmClose.headerTitle}
|
||||||
|
</AlertDialogTitle>
|
||||||
|
<AlertDialogDescription>
|
||||||
|
{translations.alerts.confirmClose.bodyText}
|
||||||
|
</AlertDialogDescription>
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<AlertDialogCancel onClick={() => setShowCloseAlert(false)}>
|
||||||
|
{translations.alerts.confirmClose.cancelButtonTitle}
|
||||||
|
</AlertDialogCancel>
|
||||||
|
<AlertDialogAction onClick={onClose}>
|
||||||
|
{translations.alerts.confirmClose.exitButtonTitle}
|
||||||
|
</AlertDialogAction>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialogPortal>
|
||||||
|
</AlertDialog>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export const ColumnGrid = <T extends string>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[calc(100vh-9.5rem)] flex-col">
|
<div className="flex h-[calc(100vh-10rem)] flex-col">
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<div className="px-8 py-6">
|
<div className="px-8 py-6">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
@@ -94,7 +94,7 @@ export const ColumnGrid = <T extends string>({
|
|||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t bg-muted px-8 py-4">
|
<div className="border-t bg-muted px-8 py-4 -mb-1">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
{onBack && (
|
{onBack && (
|
||||||
<Button variant="outline" onClick={onBack}>
|
<Button variant="outline" onClick={onBack}>
|
||||||
|
|||||||
@@ -21,16 +21,14 @@ import {
|
|||||||
AccordionTrigger,
|
AccordionTrigger,
|
||||||
} from "@/components/ui/accordion"
|
} from "@/components/ui/accordion"
|
||||||
import { Check } from "lucide-react"
|
import { Check } from "lucide-react"
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
type TemplateColumnProps<T extends string> = {
|
type TemplateColumnProps<T extends string> = {
|
||||||
column: Column<T>
|
column: Column<T>
|
||||||
onChange: (value: T, columnIndex: number) => void
|
onChange: (value: T, columnIndex: number) => void
|
||||||
onSubChange: (value: string, columnIndex: number, entry: string) => void
|
onSubChange: (value: string, columnIndex: number, entry: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAccordionTitle = <T extends string>(fields: Fields<T>, column: Column<T>, translations: any) => {
|
const getAccordionTitle = <T extends string>(fields: Fields<T>, column: Column<T>, translations: any) => {
|
||||||
const fieldLabel = fields.find((field) => "value" in column && field.key === column.value)!.label
|
const fieldLabel = fields.find((field: Field<T>) => "value" in column && field.key === column.value)!.label
|
||||||
return `${translations.matchColumnsStep.matchDropdownTitle} ${fieldLabel} (${
|
return `${translations.matchColumnsStep.matchDropdownTitle} ${fieldLabel} (${
|
||||||
"matchedOptions" in column && column.matchedOptions.filter((option) => !option.value).length
|
"matchedOptions" in column && column.matchedOptions.filter((option) => !option.value).length
|
||||||
} ${translations.matchColumnsStep.unmatched})`
|
} ${translations.matchColumnsStep.unmatched})`
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { X, RotateCcw } from "lucide-react"
|
|||||||
import type { Column } from "../MatchColumnsStep"
|
import type { Column } from "../MatchColumnsStep"
|
||||||
import { ColumnType } from "../MatchColumnsStep"
|
import { ColumnType } from "../MatchColumnsStep"
|
||||||
import type { RawData } from "../../../types"
|
import type { RawData } from "../../../types"
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
|
|
||||||
type UserTableColumnProps<T extends string> = {
|
type UserTableColumnProps<T extends string> = {
|
||||||
column: Column<T>
|
column: Column<T>
|
||||||
|
|||||||
@@ -25,23 +25,20 @@ export const SelectHeaderStep = ({ data, onContinue, onBack }: SelectHeaderProps
|
|||||||
}, [onContinue, data, selectedRows])
|
}, [onContinue, data, selectedRows])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex flex-col">
|
||||||
<div className="flex-1 overflow-hidden">
|
|
||||||
<div className="px-8 py-6">
|
<div className="px-8 py-6">
|
||||||
<div className="mb-8">
|
<h2 className="text-2xl font-semibold text-foreground">
|
||||||
<h2 className="text-3xl font-semibold text-foreground">
|
|
||||||
{translations.selectHeaderStep.title}
|
{translations.selectHeaderStep.title}
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex-1 px-8 mb-12 overflow-auto">
|
||||||
<SelectHeaderTable
|
<SelectHeaderTable
|
||||||
data={data}
|
data={data}
|
||||||
selectedRows={selectedRows}
|
selectedRows={selectedRows}
|
||||||
setSelectedRows={setSelectedRows}
|
setSelectedRows={setSelectedRows}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="flex items-center justify-between border-t bg-muted px-8 py-4 mt-2">
|
||||||
<div className="border-t bg-muted px-8 py-4 mt-5">
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
{onBack && (
|
{onBack && (
|
||||||
<Button variant="outline" onClick={onBack}>
|
<Button variant="outline" onClick={onBack}>
|
||||||
{translations.selectHeaderStep.backButtonTitle}
|
{translations.selectHeaderStep.backButtonTitle}
|
||||||
@@ -56,6 +53,5 @@ export const SelectHeaderStep = ({ data, onContinue, onBack }: SelectHeaderProps
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const SelectSheetStep = ({ sheetNames, onContinue, onBack }: SelectSheetP
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[calc(100vh-9.5rem)] flex-col">
|
<div className="flex h-[calc(100vh-10rem)] flex-col">
|
||||||
<div className="flex-1 overflow-hidden">
|
<div className="flex-1 overflow-hidden">
|
||||||
<div className="px-8 py-6">
|
<div className="px-8 py-6">
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
@@ -53,7 +53,7 @@ export const SelectSheetStep = ({ sheetNames, onContinue, onBack }: SelectSheetP
|
|||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between border-t p-6 bg-muted">
|
<div className="flex items-center justify-between border-t px-8 py-4 bg-muted -mb-1">
|
||||||
{onBack && (
|
{onBack && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
@@ -3,23 +3,14 @@ import { useRsi } from "../hooks/useRsi"
|
|||||||
import { useRef, useState } from "react"
|
import { useRef, useState } from "react"
|
||||||
import { steps, stepTypeToStepIndex, stepIndexToStepType } from "../utils/steps"
|
import { steps, stepTypeToStepIndex, stepIndexToStepType } from "../utils/steps"
|
||||||
import { CgCheck } from "react-icons/cg"
|
import { CgCheck } from "react-icons/cg"
|
||||||
import { Separator } from "@/components/ui/separator"
|
|
||||||
// @ts-ignore
|
|
||||||
import { useSteps, Step, Steps as Stepper } from "chakra-ui-steps"
|
|
||||||
|
|
||||||
const CheckIcon = ({ color }: { color: string }) => <CgCheck size="24" className={color} />
|
const CheckIcon = ({ color }: { color: string }) => <CgCheck size="24" className={color} />
|
||||||
|
|
||||||
export const Steps = () => {
|
export const Steps = () => {
|
||||||
const { initialStepState, translations, isNavigationEnabled } = useRsi()
|
const { initialStepState, translations, isNavigationEnabled } = useRsi()
|
||||||
|
|
||||||
const initialStep = stepTypeToStepIndex(initialStepState?.type)
|
const initialStep = stepTypeToStepIndex(initialStepState?.type)
|
||||||
|
const [activeStep, setActiveStep] = useState(initialStep)
|
||||||
const { nextStep, activeStep, setStep } = useSteps({
|
|
||||||
initialStep,
|
|
||||||
})
|
|
||||||
|
|
||||||
const [state, setState] = useState<StepState>(initialStepState || { type: StepType.upload })
|
const [state, setState] = useState<StepState>(initialStepState || { type: StepType.upload })
|
||||||
|
|
||||||
const history = useRef<StepState[]>([])
|
const history = useRef<StepState[]>([])
|
||||||
|
|
||||||
const onClickStep = (stepIndex: number) => {
|
const onClickStep = (stepIndex: number) => {
|
||||||
@@ -29,7 +20,7 @@ export const Steps = () => {
|
|||||||
const nextHistory = history.current.slice(0, historyIdx + 1)
|
const nextHistory = history.current.slice(0, historyIdx + 1)
|
||||||
history.current = nextHistory
|
history.current = nextHistory
|
||||||
setState(nextHistory[nextHistory.length - 1])
|
setState(nextHistory[nextHistory.length - 1])
|
||||||
setStep(stepIndex)
|
setActiveStep(stepIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
@@ -39,7 +30,7 @@ export const Steps = () => {
|
|||||||
const onNext = (v: StepState) => {
|
const onNext = (v: StepState) => {
|
||||||
history.current.push(state)
|
history.current.push(state)
|
||||||
setState(v)
|
setState(v)
|
||||||
v.type !== StepType.selectSheet && nextStep()
|
v.type !== StepType.selectSheet && setActiveStep(activeStep + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -79,7 +70,6 @@ export const Steps = () => {
|
|||||||
{translations[key].title}
|
{translations[key].title}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useCallback, useState } from "react"
|
import { useCallback, useState } from "react"
|
||||||
import { Progress, useToast } from "@chakra-ui/react"
|
import type XLSX from "xlsx"
|
||||||
import type XLSX from "xlsx-ugnis"
|
|
||||||
import { UploadStep } from "./UploadStep/UploadStep"
|
import { UploadStep } from "./UploadStep/UploadStep"
|
||||||
import { SelectHeaderStep } from "./SelectHeaderStep/SelectHeaderStep"
|
import { SelectHeaderStep } from "./SelectHeaderStep/SelectHeaderStep"
|
||||||
import { SelectSheetStep } from "./SelectSheetStep/SelectSheetStep"
|
import { SelectSheetStep } from "./SelectSheetStep/SelectSheetStep"
|
||||||
@@ -11,6 +10,8 @@ import { MatchColumnsStep } from "./MatchColumnsStep/MatchColumnsStep"
|
|||||||
import { exceedsMaxRecords } from "../utils/exceedsMaxRecords"
|
import { exceedsMaxRecords } from "../utils/exceedsMaxRecords"
|
||||||
import { useRsi } from "../hooks/useRsi"
|
import { useRsi } from "../hooks/useRsi"
|
||||||
import type { RawData } from "../types"
|
import type { RawData } from "../types"
|
||||||
|
import { Progress } from "@/components/ui/progress"
|
||||||
|
import { useToast } from "@/hooks/use-toast"
|
||||||
|
|
||||||
export enum StepType {
|
export enum StepType {
|
||||||
upload = "upload",
|
upload = "upload",
|
||||||
@@ -59,16 +60,13 @@ export const UploadFlow = ({ state, onNext, onBack }: Props) => {
|
|||||||
tableHook,
|
tableHook,
|
||||||
} = useRsi()
|
} = useRsi()
|
||||||
const [uploadedFile, setUploadedFile] = useState<File | null>(null)
|
const [uploadedFile, setUploadedFile] = useState<File | null>(null)
|
||||||
const toast = useToast()
|
const { toast } = useToast()
|
||||||
const errorToast = useCallback(
|
const errorToast = useCallback(
|
||||||
(description: string) => {
|
(description: string) => {
|
||||||
toast({
|
toast({
|
||||||
status: "error",
|
variant: "destructive",
|
||||||
variant: "left-accent",
|
title: translations.alerts.toast.error,
|
||||||
position: "bottom-left",
|
|
||||||
title: `${translations.alerts.toast.error}`,
|
|
||||||
description,
|
description,
|
||||||
isClosable: true,
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
[toast, translations],
|
[toast, translations],
|
||||||
@@ -165,6 +163,6 @@ export const UploadFlow = ({ state, onNext, onBack }: Props) => {
|
|||||||
case StepType.validateData:
|
case StepType.validateData:
|
||||||
return <ValidationStep initialData={state.data} file={uploadedFile!} onBack={onBack} />
|
return <ValidationStep initialData={state.data} file={uploadedFile!} onBack={onBack} />
|
||||||
default:
|
default:
|
||||||
return <Progress isIndeterminate />
|
return <Progress value={33} className="w-full" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import type XLSX from "xlsx-ugnis"
|
import type XLSX from "xlsx-ugnis"
|
||||||
import { Box, Heading, ModalBody, Text, useStyleConfig } from "@chakra-ui/react"
|
|
||||||
import { DropZone } from "./components/DropZone"
|
|
||||||
import { useRsi } from "../../hooks/useRsi"
|
|
||||||
import { ExampleTable } from "./components/ExampleTable"
|
|
||||||
import { useCallback, useState } from "react"
|
import { useCallback, useState } from "react"
|
||||||
|
import { useRsi } from "../../hooks/useRsi"
|
||||||
|
import { DropZone } from "./components/DropZone"
|
||||||
|
import { ExampleTable } from "./components/ExampleTable"
|
||||||
import { FadingOverlay } from "./components/FadingOverlay"
|
import { FadingOverlay } from "./components/FadingOverlay"
|
||||||
import type { themeOverrides } from "../../theme"
|
|
||||||
|
|
||||||
type UploadProps = {
|
type UploadProps = {
|
||||||
onContinue: (data: XLSX.WorkBook, file: File) => Promise<void>
|
onContinue: (data: XLSX.WorkBook, file: File) => Promise<void>
|
||||||
@@ -13,8 +11,8 @@ type UploadProps = {
|
|||||||
|
|
||||||
export const UploadStep = ({ onContinue }: UploadProps) => {
|
export const UploadStep = ({ onContinue }: UploadProps) => {
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const styles = useStyleConfig("UploadStep") as (typeof themeOverrides)["components"]["UploadStep"]["baseStyle"]
|
|
||||||
const { translations, fields } = useRsi()
|
const { translations, fields } = useRsi()
|
||||||
|
|
||||||
const handleOnContinue = useCallback(
|
const handleOnContinue = useCallback(
|
||||||
async (data: XLSX.WorkBook, file: File) => {
|
async (data: XLSX.WorkBook, file: File) => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
@@ -23,16 +21,19 @@ export const UploadStep = ({ onContinue }: UploadProps) => {
|
|||||||
},
|
},
|
||||||
[onContinue],
|
[onContinue],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalBody>
|
<div className="p-6">
|
||||||
<Heading sx={styles.heading}>{translations.uploadStep.title}</Heading>
|
<h2 className="text-2xl font-semibold mb-4">{translations.uploadStep.title}</h2>
|
||||||
<Text sx={styles.title}>{translations.uploadStep.manifestTitle}</Text>
|
<p className="text-lg mb-2">{translations.uploadStep.manifestTitle}</p>
|
||||||
<Text sx={styles.subtitle}>{translations.uploadStep.manifestDescription}</Text>
|
<p className="text-muted-foreground mb-6">{translations.uploadStep.manifestDescription}</p>
|
||||||
<Box sx={styles.tableWrapper}>
|
<div className="relative mb-0 border-t rounded-lg h-[80px]">
|
||||||
|
<div className="absolute inset-0">
|
||||||
<ExampleTable fields={fields} />
|
<ExampleTable fields={fields} />
|
||||||
|
</div>
|
||||||
<FadingOverlay />
|
<FadingOverlay />
|
||||||
</Box>
|
</div>
|
||||||
<DropZone onContinue={handleOnContinue} isLoading={isLoading} />
|
<DropZone onContinue={handleOnContinue} isLoading={isLoading} />
|
||||||
</ModalBody>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,5 +12,14 @@ export const ExampleTable = <T extends string>({ fields }: Props<T>) => {
|
|||||||
const data = useMemo(() => generateExampleRow(fields), [fields])
|
const data = useMemo(() => generateExampleRow(fields), [fields])
|
||||||
const columns = useMemo(() => generateColumns(fields), [fields])
|
const columns = useMemo(() => generateColumns(fields), [fields])
|
||||||
|
|
||||||
return <Table rows={data} columns={columns} className={"rdg-example"} />
|
return (
|
||||||
|
<div className="h-full w-full">
|
||||||
|
<Table
|
||||||
|
rows={data}
|
||||||
|
columns={columns}
|
||||||
|
className="rdg-example h-full"
|
||||||
|
style={{ height: '100%' }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
import { Box } from "@chakra-ui/react"
|
|
||||||
|
|
||||||
export const FadingOverlay = () => (
|
export const FadingOverlay = () => (
|
||||||
<Box
|
<div
|
||||||
position="absolute"
|
className="absolute inset-x-0 bottom-0 h-12 pointer-events-none bg-gradient-to-t from-background to-transparent"
|
||||||
left={0}
|
|
||||||
right={0}
|
|
||||||
bottom={0}
|
|
||||||
height="48px"
|
|
||||||
pointerEvents="none"
|
|
||||||
bgGradient="linear(to bottom, backgroundAlpha, background)"
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import type { Column } from "react-data-grid"
|
import type { Column } from "react-data-grid"
|
||||||
import { Box, Tooltip } from "@chakra-ui/react"
|
|
||||||
import type { Fields } from "../../../types"
|
import type { Fields } from "../../../types"
|
||||||
import { CgInfo } from "react-icons/cg"
|
import { CgInfo } from "react-icons/cg"
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip"
|
||||||
|
|
||||||
export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
||||||
fields.map(
|
fields.map(
|
||||||
@@ -10,23 +15,30 @@ export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
|||||||
name: column.label,
|
name: column.label,
|
||||||
minWidth: 150,
|
minWidth: 150,
|
||||||
headerRenderer: () => (
|
headerRenderer: () => (
|
||||||
<Box display="flex" gap={1} alignItems="center" position="relative">
|
<div className="flex items-center gap-1 relative">
|
||||||
<Box flex={1} overflow="hidden" textOverflow="ellipsis">
|
<div className="flex-1 overflow-hidden text-ellipsis">
|
||||||
{column.label}
|
{column.label}
|
||||||
</Box>
|
</div>
|
||||||
{column.description && (
|
{column.description && (
|
||||||
<Tooltip placement="top" hasArrow label={column.description}>
|
<TooltipProvider>
|
||||||
<Box flex={"0 0 auto"}>
|
<Tooltip>
|
||||||
<CgInfo size="16px" />
|
<TooltipTrigger asChild>
|
||||||
</Box>
|
<div className="flex-none">
|
||||||
|
<CgInfo className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
{column.description}
|
||||||
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</div>
|
||||||
),
|
),
|
||||||
formatter: ({ row }) => (
|
formatter: ({ row }) => (
|
||||||
<Box minWidth="100%" minHeight="100%" overflow="hidden" textOverflow="ellipsis">
|
<div className="min-w-full min-h-full overflow-hidden text-ellipsis">
|
||||||
{row[column.key]}
|
{row[column.key]}
|
||||||
</Box>
|
</div>
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user