feat: update permissions

This commit is contained in:
ivannoskov
2026-02-10 17:15:38 +03:00
parent 6941915d76
commit e1117e46c8
13 changed files with 961 additions and 523 deletions

View File

@@ -15,6 +15,7 @@ import {
} from "@/components/ui/dropdown-menu";
import { Checkbox } from "@/components/ui/checkbox";
import { Badge } from "@/components/ui/badge";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { useWorkspace } from "@/components/providers/workspace-provider";
import { cn } from "@/lib/utils";
@@ -30,7 +31,7 @@ export const ProjectSelector: React.FC = () => {
if (isLoadingProjects) {
return (
<div className="w-[240px] h-11 rounded-lg border border-input bg-background animate-pulse" />
<div className="w-[240px] h-10 rounded-lg border border-input bg-background animate-pulse" />
);
}
@@ -44,45 +45,56 @@ export const ProjectSelector: React.FC = () => {
const allSelected = selectedProjects.length === projects.length;
const getAvatarUrl = (project: typeof projects[0]) => {
return project.username
? `https://t.me/i/userpic/320/${project.username}.jpg`
: null;
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
variant="outline"
className="w-[280px] h-auto min-h-[44px] py-2 px-3 rounded-lg justify-between"
className="w-[240px] h-10 px-3 rounded-lg justify-start gap-2"
>
<div className="flex flex-col items-start text-left overflow-hidden">
{selectedProjects.length === 0 ? (
<span className="text-muted-foreground">Выберите проекты</span>
) : selectedProjects.length === 1 ? (
<>
<span className="font-semibold text-base truncate max-w-[220px]">
{selectedProjects[0].title}
</span>
{selectedProjects[0].username && (
<span className="text-xs text-muted-foreground -mt-0.5">
@{selectedProjects[0].username}
</span>
)}
</>
) : allSelected ? (
<span className="font-semibold text-base">Все проекты</span>
) : (
<>
<span className="font-semibold text-base">
{selectedProjects.length} проекта
</span>
<span className="text-xs text-muted-foreground -mt-0.5 truncate max-w-[220px]">
{selectedProjects.map((p) => p.title).join(", ")}
</span>
</>
)}
</div>
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50" />
{selectedProjects.length === 0 ? (
<>
<span className="text-muted-foreground">Все проекты</span>
</>
) : selectedProjects.length === 1 ? (
<>
<Avatar className="h-6 w-6 shrink-0">
<AvatarImage src={getAvatarUrl(selectedProjects[0]) || undefined} />
<AvatarFallback className="text-xs">
{selectedProjects[0].title.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
<span className="truncate max-w-[180px]">
{selectedProjects[0].title}
</span>
</>
) : allSelected ? (
<>
<span className="font-medium">Все проекты</span>
</>
) : (
<>
<Avatar className="h-6 w-6 shrink-0">
<AvatarFallback className="text-xs">
{selectedProjects.length}
</AvatarFallback>
</Avatar>
<span className="truncate max-w-[180px]">
{selectedProjects.length} проекта
</span>
</>
)}
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50 ml-auto" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[280px] p-2" align="start">
<DropdownMenuContent className="w-[240px] p-2" align="start">
{/* Quick actions */}
<div className="flex gap-2 mb-2">
<Button
@@ -117,7 +129,7 @@ export const ProjectSelector: React.FC = () => {
<div
key={project.id}
className={cn(
"flex items-center gap-3 px-2 py-2 rounded-md cursor-pointer hover:bg-accent",
"flex items-center gap-2 px-2 py-1.5 rounded-md cursor-pointer hover:bg-accent",
isSelected && "bg-accent/50"
)}
onClick={() => !isOnlyOne && toggleProject(project)}
@@ -128,15 +140,13 @@ export const ProjectSelector: React.FC = () => {
onCheckedChange={() => !isOnlyOne && toggleProject(project)}
className="shrink-0"
/>
<Tv className="h-4 w-4 text-muted-foreground shrink-0" />
<div className="flex flex-col min-w-0 flex-1">
<span className="font-medium truncate">{project.title}</span>
{project.username && (
<span className="text-xs text-muted-foreground">
@{project.username}
</span>
)}
</div>
<Avatar className="h-5 w-5 shrink-0">
<AvatarImage src={getAvatarUrl(project) || undefined} />
<AvatarFallback className="text-[10px]">
{project.title.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
<span className="truncate text-sm">{project.title}</span>
</div>
);
})}