Shadcn conversion, more styling, sheet select step
This commit is contained in:
@@ -1,8 +1,12 @@
|
|||||||
import type React from "react"
|
import type React from "react"
|
||||||
import type { Column, Columns } from "../MatchColumnsStep"
|
import type { Column, Columns } from "../MatchColumnsStep"
|
||||||
|
import { ColumnType } from "../MatchColumnsStep"
|
||||||
import { useRsi } from "../../../hooks/useRsi"
|
import { useRsi } from "../../../hooks/useRsi"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
|
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"
|
||||||
|
import { Box } from "@/components/ui/box"
|
||||||
|
import { Text } from "@/components/ui/text"
|
||||||
|
import { FadingWrapper } from "@/components/ui/fading-wrapper"
|
||||||
|
|
||||||
type ColumnGridProps<T extends string> = {
|
type ColumnGridProps<T extends string> = {
|
||||||
columns: Columns<T>
|
columns: Columns<T>
|
||||||
@@ -22,9 +26,13 @@ export const ColumnGrid = <T extends string>({
|
|||||||
isLoading,
|
isLoading,
|
||||||
}: ColumnGridProps<T>) => {
|
}: ColumnGridProps<T>) => {
|
||||||
const { translations } = useRsi()
|
const { translations } = useRsi()
|
||||||
const columnWidth = 250
|
const normalColumnWidth = 250
|
||||||
|
const ignoredColumnWidth = 48 // 12 units = 3rem = 48px
|
||||||
const gap = 16
|
const gap = 16
|
||||||
const totalWidth = columns.length * columnWidth + (columns.length - 1) * gap
|
const totalWidth = columns.reduce((acc, col) =>
|
||||||
|
acc + (col.type === ColumnType.ignored ? ignoredColumnWidth : normalColumnWidth) + gap,
|
||||||
|
-gap // Subtract one gap since we need gaps between columns only
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-[calc(100vh-9.5rem)] flex-col">
|
<div className="flex h-[calc(100vh-9.5rem)] flex-col">
|
||||||
@@ -44,18 +52,20 @@ export const ColumnGrid = <T extends string>({
|
|||||||
</h3>
|
</h3>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<div
|
<div
|
||||||
className="grid gap-4"
|
className="grid auto-cols-fr gap-4"
|
||||||
style={{
|
style={{
|
||||||
gridTemplateColumns: `repeat(${columns.length}, ${columnWidth}px)`,
|
gridTemplateColumns: columns.map(col =>
|
||||||
|
`${col.type === ColumnType.ignored ? ignoredColumnWidth : normalColumnWidth}px`
|
||||||
|
).join(" "),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{columns.map((column, index) => (
|
{columns.map((column, index) => (
|
||||||
<div key={column.header + index} className="relative">
|
<div key={column.header + index}>
|
||||||
{userColumn(column)}
|
{userColumn(column)}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="pointer-events-none absolute bottom-0 left-0 right-0 h-24 bg-gradient-to-b from-transparent to-background" />
|
<div className="pointer-events-none absolute bottom-0 left-0 right-0 h-16 bg-gradient-to-b from-transparent via-background/50 to-background" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -65,9 +75,11 @@ export const ColumnGrid = <T extends string>({
|
|||||||
{translations.matchColumnsStep.templateTitle}
|
{translations.matchColumnsStep.templateTitle}
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<div
|
||||||
className="grid gap-4"
|
className="grid auto-cols-fr gap-4"
|
||||||
style={{
|
style={{
|
||||||
gridTemplateColumns: `repeat(${columns.length}, ${columnWidth}px)`,
|
gridTemplateColumns: columns.map(col =>
|
||||||
|
`${col.type === ColumnType.ignored ? ignoredColumnWidth : normalColumnWidth}px`
|
||||||
|
).join(" "),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{columns.map((column, index) => (
|
{columns.map((column, index) => (
|
||||||
|
|||||||
@@ -49,15 +49,7 @@ export const TemplateColumn = <T extends string>({ column, onChange, onSubChange
|
|||||||
selectOptions.find(({ value }: { value: string }) => "value" in column && column.value === value)?.value
|
selectOptions.find(({ value }: { value: string }) => "value" in column && column.value === value)?.value
|
||||||
|
|
||||||
if (isIgnored) {
|
if (isIgnored) {
|
||||||
return (
|
return null
|
||||||
<Card className="h-full opacity-50">
|
|
||||||
<CardHeader className="p-4">
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
{translations.matchColumnsStep.ignoredColumnText}
|
|
||||||
</p>
|
|
||||||
</CardHeader>
|
|
||||||
</Card>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -86,8 +78,8 @@ export const TemplateColumn = <T extends string>({ column, onChange, onSubChange
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
{isChecked && (
|
{isChecked && (
|
||||||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-primary/10">
|
<div className="flex h-8 w-8 items-center justify-center rounded-full border border-green-700 bg-green-300 dark:bg-green-900/20">
|
||||||
<Check className="h-4 w-4 text-primary" />
|
<Check className="h-4 w-4 text-green-700 dark:text-green-500" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card"
|
import { Card, CardContent, CardHeader } from "@/components/ui/card"
|
||||||
import { X, Undo2 } from "lucide-react"
|
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"
|
||||||
@@ -22,35 +22,52 @@ export const UserTableColumn = <T extends string>(props: UserTableColumnProps<T>
|
|||||||
} = props
|
} = props
|
||||||
const isIgnored = type === ColumnType.ignored
|
const isIgnored = type === ColumnType.ignored
|
||||||
|
|
||||||
|
if (isIgnored) {
|
||||||
return (
|
return (
|
||||||
<Card className={cn(
|
<Card className="h-full w-12 bg-muted/50">
|
||||||
"h-full transition-opacity",
|
<CardHeader className="flex flex-col items-center space-y-4 p-2">
|
||||||
isIgnored && "opacity-50"
|
|
||||||
)}>
|
|
||||||
<CardHeader className="flex flex-row items-center justify-between space-x-2 p-4">
|
|
||||||
<h4 className="truncate font-medium leading-none">
|
|
||||||
{header}
|
|
||||||
</h4>
|
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
onClick={() => isIgnored ? onRevertIgnore(index) : onIgnore(index)}
|
onClick={() => onRevertIgnore(index)}
|
||||||
className="h-8 w-8 shrink-0"
|
className="h-8 w-8"
|
||||||
>
|
>
|
||||||
{isIgnored ? <Undo2 className="h-4 w-4" /> : <X className="h-4 w-4" />}
|
<RotateCcw className="h-4 w-4" />
|
||||||
|
</Button>
|
||||||
|
<div
|
||||||
|
className="vertical-text font-medium text-muted-foreground"
|
||||||
|
style={{ writingMode: 'vertical-rl', textOrientation: 'mixed', transform: 'rotate(180deg)' }}
|
||||||
|
>
|
||||||
|
{header}
|
||||||
|
</div>
|
||||||
|
</CardHeader>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="h-full">
|
||||||
|
<CardHeader className="flex flex-row items-center justify-between space-x-2 p-4">
|
||||||
|
<p className="font-medium">
|
||||||
|
{header}
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
onClick={() => onIgnore(index)}
|
||||||
|
className="h-8 w-8"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
</Button>
|
</Button>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-2 p-4">
|
<CardContent className="space-y-2 p-4">
|
||||||
{entries.slice(0, 3).map((entry, i) => (
|
{entries.map((entry, i) => (
|
||||||
<div
|
<p
|
||||||
key={`${entry || ""}-${i}`}
|
key={`${entry || ""}-${i}`}
|
||||||
className={cn(
|
className="truncate text-sm text-muted-foreground"
|
||||||
"truncate px-3 py-2 text-sm",
|
|
||||||
isIgnored ? "text-muted-foreground" : "text-foreground"
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{entry || ""}
|
{entry}
|
||||||
</div>
|
</p>
|
||||||
))}
|
))}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Heading, ModalBody, Radio, RadioGroup, Stack, useStyleConfig, Text } from "@chakra-ui/react"
|
|
||||||
import { useCallback, useState } from "react"
|
import { useCallback, useState } from "react"
|
||||||
import { ContinueButton } from "../../components/ContinueButton"
|
|
||||||
import { useRsi } from "../../hooks/useRsi"
|
import { useRsi } from "../../hooks/useRsi"
|
||||||
import type { themeOverrides } from "../../theme"
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
|
||||||
|
import { Label } from "@/components/ui/label"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { ChevronLeft } from "lucide-react"
|
||||||
|
|
||||||
type SelectSheetProps = {
|
type SelectSheetProps = {
|
||||||
sheetNames: string[]
|
sheetNames: string[]
|
||||||
@@ -14,9 +15,7 @@ export const SelectSheetStep = ({ sheetNames, onContinue, onBack }: SelectSheetP
|
|||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const { translations } = useRsi()
|
const { translations } = useRsi()
|
||||||
const [value, setValue] = useState(sheetNames[0])
|
const [value, setValue] = useState(sheetNames[0])
|
||||||
const styles = useStyleConfig(
|
|
||||||
"SelectSheetStep",
|
|
||||||
) as (typeof themeOverrides)["components"]["SelectSheetStep"]["baseStyle"]
|
|
||||||
const handleOnContinue = useCallback(
|
const handleOnContinue = useCallback(
|
||||||
async (data: typeof value) => {
|
async (data: typeof value) => {
|
||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
@@ -27,26 +26,52 @@ export const SelectSheetStep = ({ sheetNames, onContinue, onBack }: SelectSheetP
|
|||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="flex h-[calc(100vh-9.5rem)] flex-col">
|
||||||
<ModalBody alignItems="center" justifyContent="center" p={8} flex={1}>
|
<div className="flex-1 overflow-hidden">
|
||||||
<Heading {...styles.heading}>{translations.uploadStep.selectSheet.title}</Heading>
|
<div className="px-8 py-6">
|
||||||
<RadioGroup onChange={(value) => setValue(value)} value={value}>
|
<div className="mb-8">
|
||||||
<Stack spacing={8}>
|
<h2 className="text-3xl font-semibold text-foreground">
|
||||||
|
{translations.uploadStep.selectSheet.title}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<RadioGroup
|
||||||
|
value={value}
|
||||||
|
onValueChange={setValue}
|
||||||
|
className="space-y-4"
|
||||||
|
>
|
||||||
{sheetNames.map((sheetName) => (
|
{sheetNames.map((sheetName) => (
|
||||||
<Radio value={sheetName} key={sheetName} {...styles.radio}>
|
<div key={sheetName} className="flex items-center space-x-2">
|
||||||
<Text {...styles.radioLabel}>{sheetName}</Text>
|
<RadioGroupItem value={sheetName} id={sheetName} />
|
||||||
</Radio>
|
<Label
|
||||||
|
htmlFor={sheetName}
|
||||||
|
className="text-base"
|
||||||
|
>
|
||||||
|
{sheetName}
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</Stack>
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
</ModalBody>
|
</div>
|
||||||
<ContinueButton
|
</div>
|
||||||
isLoading={isLoading}
|
<div className="flex items-center justify-between border-t p-6 bg-muted">
|
||||||
onContinue={() => handleOnContinue(value)}
|
{onBack && (
|
||||||
onBack={onBack}
|
<Button
|
||||||
title={translations.uploadStep.selectSheet.nextButtonTitle}
|
variant="ghost"
|
||||||
backTitle={translations.uploadStep.selectSheet.backButtonTitle}
|
onClick={onBack}
|
||||||
/>
|
className="gap-2"
|
||||||
</>
|
>
|
||||||
|
<ChevronLeft className="h-4 w-4" />
|
||||||
|
{translations.uploadStep.selectSheet.backButtonTitle}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<div className="flex-1" />
|
||||||
|
<Button
|
||||||
|
onClick={() => handleOnContinue(value)}
|
||||||
|
disabled={isLoading}
|
||||||
|
>
|
||||||
|
{translations.uploadStep.selectSheet.nextButtonTitle}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user