pinterest-like-image-gallery

Форк
0
85 строк · 3.2 Кб
1
import { useEffect, useState, ChangeEvent, KeyboardEvent } from "react";
2
import { Gallery } from "@/components";
3
import { useDispatch, useSelector } from 'react-redux';
4
import { addItem, removeItem, setImageUrl, setComment, setItems } from '../../store/slice';
5
import { RootState } from "@/store/store";
6
import { loadFromLocalStorage } from '@/store/helpers';
7
import useIsClient from "@/utils/IsClient";
8

9
const GalleryManager = () => {
10
  const [error, setError] = useState<string | null>(null);
11
  const dispatch = useDispatch();
12
  const galleryItems = useSelector((state: RootState) => state.gallery.items);
13
  const imageUrl = useSelector((state: RootState) => state.gallery.imageUrl);
14
  const comment = useSelector((state: RootState) => state.gallery.comment);
15
  const isClient = useIsClient();
16

17
  const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
18
    const value = event.target.value;
19
    dispatch(setImageUrl(value));
20

21
    if (value && !isValidURL(value)) {
22
        setError('Please enter a valid URL');
23
    } else {
24
        setError(null);
25
    }
26
  };
27

28
  const handleCommentChange = (event: ChangeEvent<HTMLInputElement>) => {
29
    dispatch(setComment(event.target.value));
30
  };
31

32
  const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
33
    if (event.key === 'Enter' && imageUrl.trim() !== '' && !error) {
34
      dispatch(addItem());
35
    }
36
  };
37

38
  const handleRemoveImage = (idToRemove: number) => {
39
    dispatch(removeItem(idToRemove));
40
  }
41

42
  useEffect(() => {
43
    if (isClient) {
44
      const initialState = loadFromLocalStorage();
45
      if (initialState && initialState.gallery) {
46
        dispatch(setItems(initialState.gallery.items));
47
      }
48
    }
49
  }, [isClient]);
50

51
  if (!isClient) {
52
    return <div>Loading...</div>; // заглушка на серверной стороне
53
  }
54

55
  const isValidURL = (str: string): boolean => {
56
    const pattern = new RegExp("https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)");
57
    return pattern.test(str);
58
  };
59

60
  return (
61
    <div className="bg-gray-200">
62
      <div className="container mx-auto p-4">
63
        <input
64
          type="text"
65
          value={imageUrl}
66
          onChange={handleInputChange}
67
          onKeyDown={handleKeyDown}
68
          className="bg-gray-50 border border-gray-100 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-100 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-700 dark:focus:ring-blue-500 dark:focus:border-blue-500"
69
          placeholder="Add image URL" />
70
        {error && <p className="text-red-500 text-sm mt-2">{error}</p>}
71

72
        <input
73
          type="text"
74
          value={comment}
75
          onChange={handleCommentChange}
76
          onKeyDown={handleKeyDown}
77
          className="bg-gray-50 border border-gray-100 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 mt-2 dark:bg-gray-100 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-700 dark:focus:ring-blue-500 dark:focus:border-blue-500"
78
          placeholder="Add comment" />
79
      </div>
80
        <Gallery items={galleryItems} onRemove={handleRemoveImage} />
81
    </div>
82
  );
83
};
84

85
export default GalleryManager;
86

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.