File size: 5,165 Bytes
044eef3
 
72660a6
044eef3
 
 
 
 
 
 
72660a6
 
 
 
 
 
 
 
 
044eef3
 
72660a6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a514f81
044eef3
a514f81
044eef3
 
 
 
 
72660a6
044eef3
 
72660a6
 
 
 
 
 
 
 
 
 
 
044eef3
 
 
 
 
 
 
a514f81
044eef3
 
 
 
 
72660a6
044eef3
 
72660a6
 
 
 
 
 
 
 
 
 
 
044eef3
 
 
 
 
 
 
a514f81
 
 
 
 
 
72660a6
a514f81
 
72660a6
 
 
 
 
 
 
 
 
 
 
a514f81
 
 
 
 
 
 
044eef3
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { getAllLayouts } from '../../data/layouts';
import { LayoutType } from '../../types/canvas.types';
import { useState } from 'react';

interface LayoutSelectorProps {
  onSelectLayout: (layoutId: LayoutType) => void;
}

export default function LayoutSelector({ onSelectLayout }: LayoutSelectorProps) {
  const layouts = getAllLayouts();
  const [loadingImages, setLoadingImages] = useState<Set<string>>(new Set(layouts.map(l => l.id)));

  const handleImageLoad = (layoutId: string) => {
    setLoadingImages(prev => {
      const newSet = new Set(prev);
      newSet.delete(layoutId);
      return newSet;
    });
  };

  return (
    <div
      className="layout-selector absolute left-[calc(100%+4px)] top-[5px] bg-[#f8f9fa] border border-[#3faee6] rounded-[10px] p-[5px] shadow-lg inline-block"
      onDragStart={(e) => {
        e.preventDefault();
        e.stopPropagation();
      }}
      onDrag={(e) => {
        e.preventDefault();
        e.stopPropagation();
      }}
      onDragOver={(e) => {
        e.preventDefault();
        e.stopPropagation();
      }}
    >
      {/* 2x3 Grid - 2 layouts per row, 3 rows total */}
      <div className="flex flex-col gap-0">
        {/* First Row - 2 layouts */}
        <div className="flex gap-0">
          {layouts.slice(0, 2).map((layout) => (
            <button
              key={layout.id}
              onClick={() => onSelectLayout(layout.id)}
              onDragStart={(e) => e.preventDefault()}
              className="flex flex-col items-center gap-[5px] p-[10px] rounded-[5px] hover:bg-[#e9ecef] transition-colors flex-1"
            >
              <div className="w-[96.5px] h-[47.291px] rounded-[5px] flex items-center justify-center overflow-hidden relative" onDragStart={(e) => e.preventDefault()}>
                {loadingImages.has(layout.id) && (
                  <div className="absolute inset-0 skeleton-shimmer"></div>
                )}
                <img
                  src={layout.thumbnail}
                  alt={layout.name}
                  className={`w-full h-full object-cover transition-opacity duration-200 ${loadingImages.has(layout.id) ? 'opacity-0' : 'opacity-100'}`}
                  onLoad={() => handleImageLoad(layout.id)}
                  draggable={false}
                />
              </div>
              <p className="text-[14px] font-normal text-[#545865] text-center">
                {layout.name}
              </p>
            </button>
          ))}
        </div>
        {/* Second Row - 2 layouts */}
        <div className="flex gap-0">
          {layouts.slice(2, 4).map((layout) => (
            <button
              key={layout.id}
              onClick={() => onSelectLayout(layout.id)}
              onDragStart={(e) => e.preventDefault()}
              className="flex flex-col items-center gap-[5px] p-[10px] rounded-[5px] hover:bg-[#e9ecef] transition-colors flex-1"
            >
              <div className="w-[96.5px] h-[47.291px] rounded-[5px] flex items-center justify-center overflow-hidden relative" onDragStart={(e) => e.preventDefault()}>
                {loadingImages.has(layout.id) && (
                  <div className="absolute inset-0 skeleton-shimmer"></div>
                )}
                <img
                  src={layout.thumbnail}
                  alt={layout.name}
                  className={`w-full h-full object-cover transition-opacity duration-200 ${loadingImages.has(layout.id) ? 'opacity-0' : 'opacity-100'}`}
                  onLoad={() => handleImageLoad(layout.id)}
                  draggable={false}
                />
              </div>
              <p className="text-[14px] font-normal text-[#545865] text-center">
                {layout.name}
              </p>
            </button>
          ))}
        </div>
        {/* Third Row - 1 layout (Academia Hub) */}
        <div className="flex gap-0">
          {layouts.slice(4, 6).map((layout) => (
            <button
              key={layout.id}
              onClick={() => onSelectLayout(layout.id)}
              onDragStart={(e) => e.preventDefault()}
              className="flex flex-col items-center gap-[5px] p-[10px] rounded-[5px] hover:bg-[#e9ecef] transition-colors flex-1"
            >
              <div className="w-[96.5px] h-[47.291px] rounded-[5px] flex items-center justify-center overflow-hidden relative" onDragStart={(e) => e.preventDefault()}>
                {loadingImages.has(layout.id) && (
                  <div className="absolute inset-0 skeleton-shimmer"></div>
                )}
                <img
                  src={layout.thumbnail}
                  alt={layout.name}
                  className={`w-full h-full object-cover transition-opacity duration-200 ${loadingImages.has(layout.id) ? 'opacity-0' : 'opacity-100'}`}
                  onLoad={() => handleImageLoad(layout.id)}
                  draggable={false}
                />
              </div>
              <p className="text-[14px] font-normal text-[#545865] text-center">
                {layout.name}
              </p>
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}