карточки редизайн
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
"@radix-ui/react-dialog": "^1.1.14",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
||||
"@radix-ui/react-label": "^2.1.7",
|
||||
"@radix-ui/react-popover": "^1.1.14",
|
||||
"@radix-ui/react-radio-group": "^1.3.7",
|
||||
"@radix-ui/react-select": "^2.2.5",
|
||||
"@radix-ui/react-separator": "^1.1.7",
|
||||
|
||||
28
src/component/ui/popover.tsx
Normal file
28
src/component/ui/popover.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { cn } from '@/lib/utils'
|
||||
import * as PopoverPrimitive from '@radix-ui/react-popover'
|
||||
import * as React from 'react'
|
||||
|
||||
const Popover = PopoverPrimitive.Root
|
||||
const PopoverTrigger = PopoverPrimitive.Trigger
|
||||
const PopoverAnchor = PopoverPrimitive.Anchor
|
||||
|
||||
const PopoverContent = React.forwardRef<
|
||||
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||
>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
ref={ref}
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
))
|
||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
||||
|
||||
export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger }
|
||||
@@ -132,6 +132,31 @@ export const DEFAULT_FUNCTIONS: Record<string, ExcelFunction> = {
|
||||
date.setHours(0, 0, 0, 0)
|
||||
return date.getTime()
|
||||
},
|
||||
ДАТАПРОТОКОЛА: (дата: number | Date) => {
|
||||
try {
|
||||
const months = [
|
||||
'',
|
||||
'января', 'февраля', 'марта',
|
||||
'апреля', 'мая', 'июня',
|
||||
'июля', 'августа', 'сентября',
|
||||
'октября', 'ноября', 'декабря',
|
||||
]
|
||||
let dateObj: Date
|
||||
if (typeof дата === 'number') {
|
||||
dateObj = new Date(дата)
|
||||
} else if (дата instanceof Date) {
|
||||
dateObj = дата
|
||||
} else {
|
||||
return 'Неверный формат даты'
|
||||
}
|
||||
const day = dateObj.getDate().toString().padStart(2, '0')
|
||||
const month = months[dateObj.getMonth() + 1]
|
||||
const year = dateObj.getFullYear()
|
||||
return `${day} ${month} ${year}`
|
||||
} catch (e) {
|
||||
return 'Неверный формат даты'
|
||||
}
|
||||
},
|
||||
|
||||
// Отладочная функция
|
||||
ТЕСТ: (значение: any = 'Функция работает!') => {
|
||||
|
||||
@@ -130,7 +130,7 @@ export const TemplatesOverviewPage = () => {
|
||||
<header className="flex items-center gap-2 border-b px-4 py-2">
|
||||
<SidebarTrigger />
|
||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||
<h1 className="text-lg font-semibold">Шаблоны</h1>
|
||||
<h1 className="text-lg font-semibold">Карточки протоколов</h1>
|
||||
|
||||
<div className="ml-auto flex items-center gap-2">
|
||||
{selectionMode && (
|
||||
@@ -263,8 +263,8 @@ export const TemplatesOverviewPage = () => {
|
||||
|
||||
<section
|
||||
className={clsx(
|
||||
'grid gap-6',
|
||||
'grid-cols-1 md:grid-cols-2 lg:grid-cols-3'
|
||||
'grid gap-4',
|
||||
'grid-cols-1 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5'
|
||||
)}
|
||||
>
|
||||
{filteredTemplates.map(t => (
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import { Button } from '@/component/ui/button'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/component/ui/card'
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@/component/ui/popover'
|
||||
import { Template } from '@/type/template'
|
||||
import clsx from 'clsx'
|
||||
import { CheckCircle, Circle, FileText, Settings, Wrench } from 'lucide-react'
|
||||
import {
|
||||
Check,
|
||||
FileText,
|
||||
MoreVertical,
|
||||
Pencil,
|
||||
Settings,
|
||||
Wrench,
|
||||
} from 'lucide-react'
|
||||
import React from 'react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
|
||||
@@ -35,11 +43,13 @@ const TemplateCard: React.FC<TemplateCardProps> = ({
|
||||
: undefined
|
||||
}
|
||||
className={clsx(
|
||||
'relative', // <-- добавьте этот класс!
|
||||
'border-2 ring-4 ring-offset-2',
|
||||
selectionMode && 'hover:cursor-pointer',
|
||||
selectionMode &&
|
||||
isSelected &&
|
||||
'border-2 border-primary ring-4 ring-primary/30 ring-offset-2',
|
||||
'hover:border-2 hover:border-primary'
|
||||
selectionMode && isSelected
|
||||
? 'border-primary ring-primary/30'
|
||||
: 'border-border ring-transparent',
|
||||
'hover:border-primary'
|
||||
)}
|
||||
>
|
||||
{selectionMode && (
|
||||
@@ -58,9 +68,38 @@ const TemplateCard: React.FC<TemplateCardProps> = ({
|
||||
'focus-visible:ring-2 focus-visible:ring-accent'
|
||||
)}
|
||||
>
|
||||
{isSelected ? <CheckCircle size={18} /> : <Circle size={18} />}
|
||||
{isSelected ? <Check size={18} /> : null}
|
||||
</button>
|
||||
)}
|
||||
{/* Popover-меню с действиями, только если не selectionMode */}
|
||||
{!selectionMode && (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
tabIndex={0}
|
||||
aria-label="Действия"
|
||||
className={clsx(
|
||||
'absolute right-3 top-3 z-10 flex h-7 w-7 items-center justify-center rounded-full border border-border bg-white text-muted-foreground transition-all',
|
||||
'hover:text-accent-foreground',
|
||||
'focus-visible:ring-2 focus-visible:ring-accent'
|
||||
)}
|
||||
>
|
||||
<MoreVertical className="h-4 w-4" />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" className="w-40 p-1">
|
||||
<button
|
||||
type="button"
|
||||
className="flex w-full items-center gap-2 rounded px-2 py-2 text-sm transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
<Pencil className="h-4 w-4" />
|
||||
Редактировать
|
||||
</button>
|
||||
{/* Здесь можно добавить другие действия */}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
<CardHeader className="pb-4">
|
||||
<CardTitle className="text-base font-medium">{template.name}</CardTitle>
|
||||
|
||||
36
yarn.lock
36
yarn.lock
@@ -485,6 +485,27 @@
|
||||
aria-hidden "^1.2.4"
|
||||
react-remove-scroll "^2.6.3"
|
||||
|
||||
"@radix-ui/react-popover@^1.1.14":
|
||||
version "1.1.14"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.14.tgz#5496d1986f0287cdfc77e73f70a887e4cb77ad08"
|
||||
integrity sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==
|
||||
dependencies:
|
||||
"@radix-ui/primitive" "1.1.2"
|
||||
"@radix-ui/react-compose-refs" "1.1.2"
|
||||
"@radix-ui/react-context" "1.1.2"
|
||||
"@radix-ui/react-dismissable-layer" "1.1.10"
|
||||
"@radix-ui/react-focus-guards" "1.1.2"
|
||||
"@radix-ui/react-focus-scope" "1.1.7"
|
||||
"@radix-ui/react-id" "1.1.1"
|
||||
"@radix-ui/react-popper" "1.2.7"
|
||||
"@radix-ui/react-portal" "1.1.9"
|
||||
"@radix-ui/react-presence" "1.1.4"
|
||||
"@radix-ui/react-primitive" "2.1.3"
|
||||
"@radix-ui/react-slot" "1.2.3"
|
||||
"@radix-ui/react-use-controllable-state" "1.2.2"
|
||||
aria-hidden "^1.2.4"
|
||||
react-remove-scroll "^2.6.3"
|
||||
|
||||
"@radix-ui/react-popper@1.2.7":
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.7.tgz#531cf2eebb3d3270d58f7d8136e4517646429978"
|
||||
@@ -834,7 +855,14 @@
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.0", "@types/hoist-non-react-statics@^3.3.1":
|
||||
"@types/hoist-non-react-statics@^3.3.0":
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.7.tgz#306e3a3a73828522efa1341159da4846e7573a6c"
|
||||
integrity sha512-PQTyIulDkIDro8P+IHbKCsw7U2xxBYflVzW/FgWdCAePD9xGSidgA76/GeJ6lBKoblyhf9pBY763gbrN+1dI8g==
|
||||
dependencies:
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.1":
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz#6bba74383cdab98e8db4e20ce5b4a6b98caed010"
|
||||
integrity sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==
|
||||
@@ -1687,9 +1715,9 @@ eastasianwidth@^0.2.0:
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
electron-to-chromium@^1.5.173:
|
||||
version "1.5.187"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.187.tgz#8c58854e065962351dc87e95614dd78d50425966"
|
||||
integrity sha512-cl5Jc9I0KGUoOoSbxvTywTa40uspGJt/BDBoDLoxJRSBpWh4FFXBsjNRHfQrONsV/OoEjDfHUmZQa2d6Ze4YgA==
|
||||
version "1.5.190"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.190.tgz#f0ac8be182291a45e8154dbb12f18d2b2318e4ac"
|
||||
integrity sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
|
||||
Reference in New Issue
Block a user