diff --git a/package-lock.json b/package-lock.json
index 45f9811..d58e2b6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,13 +12,17 @@
"@chakra-ui/react": "^2.1.1",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
+ "@heroicons/react": "^2.1.5",
"firebase": "^11.0.1",
"framer-motion": "^11.11.11",
"next-themes": "^0.4.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
- "react-router-dom": "^6.27.0"
+ "react-masonry-css": "^1.0.16",
+ "react-responsive-carousel": "^3.2.23",
+ "react-router-dom": "^6.27.0",
+ "react-tsparticles": "^2.12.2"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
@@ -1983,6 +1987,15 @@
"node": ">=6"
}
},
+ "node_modules/@heroicons/react": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.1.5.tgz",
+ "integrity": "sha512-FuzFN+BsHa+7OxbvAERtgBTNeZpUjgM/MIizfVkSCL2/edriN0Hx/DWRCR//aPYwO5QX/YlgLGXk+E3PcfZwjA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">= 16"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
@@ -4073,6 +4086,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+ "license": "MIT"
+ },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -8116,6 +8135,18 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-easy-swipe": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz",
+ "integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.5.8"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/react-fast-compare": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
@@ -8160,6 +8191,15 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
+ "node_modules/react-masonry-css": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/react-masonry-css/-/react-masonry-css-1.0.16.tgz",
+ "integrity": "sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": ">=16.0.0"
+ }
+ },
"node_modules/react-remove-scroll": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz",
@@ -8207,6 +8247,17 @@
}
}
},
+ "node_modules/react-responsive-carousel": {
+ "version": "3.2.23",
+ "resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz",
+ "integrity": "sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg==",
+ "license": "MIT",
+ "dependencies": {
+ "classnames": "^2.2.5",
+ "prop-types": "^15.5.8",
+ "react-easy-swipe": "^0.0.21"
+ }
+ },
"node_modules/react-router": {
"version": "6.27.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz",
@@ -8262,6 +8313,34 @@
}
}
},
+ "node_modules/react-tsparticles": {
+ "version": "2.12.2",
+ "resolved": "https://registry.npmjs.org/react-tsparticles/-/react-tsparticles-2.12.2.tgz",
+ "integrity": "sha512-/nrEbyL8UROXKIMXe+f+LZN2ckvkwV2Qa+GGe/H26oEIc+wq/ybSG9REDwQiSt2OaDQGu0MwmA4BKmkL6wAWcA==",
+ "deprecated": "@tsparticles/react is the new version, please use that",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/matteobruni"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/tsparticles"
+ },
+ {
+ "type": "buymeacoffee",
+ "url": "https://www.buymeacoffee.com/matteobruni"
+ }
+ ],
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "tsparticles-engine": "^2.12.0"
+ },
+ "peerDependencies": {
+ "react": ">=16"
+ }
+ },
"node_modules/redent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
@@ -8954,6 +9033,28 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD"
},
+ "node_modules/tsparticles-engine": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/tsparticles-engine/-/tsparticles-engine-2.12.0.tgz",
+ "integrity": "sha512-ZjDIYex6jBJ4iMc9+z0uPe7SgBnmb6l+EJm83MPIsOny9lPpetMsnw/8YJ3xdxn8hV+S3myTpTN1CkOVmFv0QQ==",
+ "deprecated": "starting from tsparticles v3 the packages are now moved to @tsparticles/package-name instead of tsparticles-package-name",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/matteobruni"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/tsparticles"
+ },
+ {
+ "type": "buymeacoffee",
+ "url": "https://www.buymeacoffee.com/matteobruni"
+ }
+ ],
+ "hasInstallScript": true,
+ "license": "MIT"
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
diff --git a/package.json b/package.json
index 6f405a1..826023b 100644
--- a/package.json
+++ b/package.json
@@ -16,12 +16,15 @@
"@chakra-ui/react": "^2.1.1",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
+ "@heroicons/react": "^2.1.5",
"firebase": "^11.0.1",
"framer-motion": "^11.11.11",
"next-themes": "^0.4.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-icons": "^5.3.0",
+ "react-masonry-css": "^1.0.16",
+ "react-responsive-carousel": "^3.2.23",
"react-router-dom": "^6.27.0"
},
"devDependencies": {
diff --git a/src/App.jsx b/src/App.jsx
index b6392d1..aa3811b 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -8,6 +8,8 @@ import Thread from './components/Thread';
import ThreadDetail from './components/ThreadDetail';
import CreateThread from './components/CreateThread';
import AdminPage from './components/AdminPage';
+import ProfileMasonry from './components/Profile/ProfileMasonry';
+import ProfileEdit from './components/ProfileEdit';
function App() {
const location = useLocation();
@@ -25,6 +27,8 @@ function App() {
} />
} />
} />
+ } />
+ } />
>
);
diff --git a/src/components/HeroCard.jsx b/src/components/HeroCard.jsx
new file mode 100644
index 0000000..a3e97d3
--- /dev/null
+++ b/src/components/HeroCard.jsx
@@ -0,0 +1,35 @@
+import { motion } from 'framer-motion';
+import { PropTypes } from 'prop-types';
+import { Avatar, Text } from '@chakra-ui/react';
+
+const HeroCard = ({ user }) => {
+ const cardVariants = {
+ hover: {
+ scale: 1.05,
+ transition: { duration: 0.2 },
+ },
+ };
+
+ HeroCard.propTypes = {
+ user: PropTypes.object.isRequired,
+ };
+
+ return (
+
+
+
+ {user.displayName || 'Anonymous'}
+
+ {user.email}
+
+ );
+};
+
+export default HeroCard;
diff --git a/src/components/Profile/AchievementCard.jsx b/src/components/Profile/AchievementCard.jsx
new file mode 100644
index 0000000..22641ed
--- /dev/null
+++ b/src/components/Profile/AchievementCard.jsx
@@ -0,0 +1,66 @@
+import { Box, Grid, HStack, Text, Icon, VStack } from '@chakra-ui/react';
+import { motion } from 'framer-motion';
+import { TrophyIcon } from '@heroicons/react/24/outline';
+
+import { PropTypes } from 'prop-types';
+
+const MotionBox = motion(Box);
+
+const AchievementBadge = ({ icon: IconComponent, name }) => (
+
+
+
+ {name}
+
+
+);
+
+AchievementBadge.propTypes = {
+ icon: PropTypes.elementType.isRequired,
+ name: PropTypes.string.isRequired,
+};
+
+const AchievementCard = ({ achievements }) => (
+
+
+
+
+ アチーブメント
+
+
+
+ {achievements.map((achievement) => (
+
+ ))}
+
+
+);
+
+AchievementCard.propTypes = {
+ achievements: PropTypes.array.isRequired,
+};
+
+export default AchievementCard;
diff --git a/src/components/Profile/HallOfFameCard.jsx b/src/components/Profile/HallOfFameCard.jsx
new file mode 100644
index 0000000..ca58c0d
--- /dev/null
+++ b/src/components/Profile/HallOfFameCard.jsx
@@ -0,0 +1,49 @@
+import { Box, HStack, Text, Icon } from '@chakra-ui/react';
+import { motion } from 'framer-motion';
+import { HiOutlineStar } from 'react-icons/hi';
+import { PropTypes } from 'prop-types';
+
+const MotionBox = motion(Box);
+
+const HallOfFameCard = ({ post }) => (
+
+
+
+
+ 殿堂入り投稿
+
+
+
+ {post.content}
+
+
+
+ {new Date(post.createdAt?.toDate()).toLocaleDateString()}
+
+
+
+ {post.likes}
+
+
+
+);
+
+HallOfFameCard.propTypes = {
+ post: PropTypes.object.isRequired,
+};
+
+export default HallOfFameCard;
diff --git a/src/components/Profile/ProfileMasonry.jsx b/src/components/Profile/ProfileMasonry.jsx
new file mode 100644
index 0000000..1229bce
--- /dev/null
+++ b/src/components/Profile/ProfileMasonry.jsx
@@ -0,0 +1,163 @@
+import { useState, useEffect } from 'react';
+import { useNavigate } from 'react-router-dom';
+import Masonry from 'react-masonry-css';
+import { Box } from '@chakra-ui/react';
+// eslint-disable-next-line no-unused-vars
+import { motion } from 'framer-motion';
+import { auth, db } from '../../config/firebase';
+import { collection, query, where, getDocs, orderBy } from 'firebase/firestore';
+import {
+ ChatBubbleBottomCenterTextIcon,
+ StarIcon,
+ FireIcon,
+ HeartIcon,
+ ChartBarIcon,
+ CheckBadgeIcon,
+} from '@heroicons/react/24/outline';
+import UserInfoCard from './UserInfoCard';
+import StatCard from './StatCard';
+import AchievementCard from './AchievementCard';
+import HallOfFameCard from './HallOfFameCard';
+import '../ProfileStyles.css';
+
+//const MotionBox = motion(Box);
+
+const ProfileMasonry = () => {
+ const navigate = useNavigate();
+ const [loading, setLoading] = useState(true);
+ const [user, setUser] = useState(null);
+ // eslint-disable-next-line no-unused-vars
+ const [userStats, setUserStats] = useState({
+ totalPosts: 0,
+ totalHallOfFame: 0,
+ streak: 0,
+ });
+ // eslint-disable-next-line no-unused-vars
+ const [achievements, setAchievements] = useState([]);
+ const [hallOfFamePosts, setHallOfFamePosts] = useState([]);
+
+ const breakpointColumns = {
+ default: 3,
+ 1100: 2,
+ 700: 1,
+ };
+
+ const mockStats = {
+ totalPosts: 42,
+ totalHallOfFame: 10,
+ streak: 5,
+ };
+
+ const mockAchievements = [
+ { id: 1, name: '初投稿', icon: ChatBubbleBottomCenterTextIcon },
+ { id: 2, name: '殿堂入り', icon: StarIcon },
+ { id: 3, name: '3日連続投稿', icon: FireIcon },
+ { id: 4, name: '人気者', icon: HeartIcon },
+ { id: 5, name: 'トレンド入り', icon: ChartBarIcon },
+ { id: 6, name: '完璧な回答', icon: CheckBadgeIcon },
+ ];
+
+ useEffect(() => {
+ const unsubscribe = auth.onAuthStateChanged((currentUser) => {
+ setUser(currentUser);
+ if (currentUser) {
+ fetchUserData(currentUser.uid);
+ } else {
+ setLoading(false);
+ navigate('/login');
+ }
+ });
+
+ return () => unsubscribe();
+ }, [navigate]);
+
+ const fetchUserData = async (uid) => {
+ try {
+ // Stats取得
+ const postsQuery = query(
+ collection(db, 'posts'),
+ where('userId', '==', uid),
+ orderBy('createdAt', 'desc')
+ );
+ const hallOfFameQuery = query(
+ collection(db, 'posts'),
+ where('userId', '==', uid),
+ where('isHallOfFame', '==', true)
+ );
+ const streakQuery = query(
+ collection(db, 'userStats'),
+ where('userId', '==', uid)
+ );
+
+ // Achievement取得
+ const achievementsQuery = query(
+ collection(db, 'achievements'),
+ where('userId', '==', uid)
+ );
+
+ const [
+ postsSnapshot,
+ hallOfFameSnapshot,
+ streakSnapshot,
+ achievementsSnapshot,
+ ] = await Promise.all([
+ getDocs(postsQuery),
+ getDocs(hallOfFameQuery),
+ getDocs(streakQuery),
+ getDocs(achievementsQuery),
+ ]);
+
+ setUserStats({
+ totalPosts: postsSnapshot.size,
+ totalHallOfFame: hallOfFameSnapshot.size,
+ streak: streakSnapshot.docs[0]?.data()?.currentStreak || 0,
+ });
+
+ setAchievements(
+ achievementsSnapshot.docs.map((doc) => ({
+ id: doc.id,
+ ...doc.data(),
+ }))
+ );
+
+ setHallOfFamePosts(
+ hallOfFameSnapshot.docs.map((doc) => ({
+ id: doc.id,
+ ...doc.data(),
+ }))
+ );
+
+ setLoading(false);
+ } catch (error) {
+ console.error('Error fetching user data:', error);
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return (
+
+ Loading...
+
+ );
+ }
+
+ return (
+
+
+
+
+
+ {hallOfFamePosts.map((post) => (
+
+ ))}
+
+
+ );
+};
+
+export default ProfileMasonry;
diff --git a/src/components/Profile/StatCard.jsx b/src/components/Profile/StatCard.jsx
new file mode 100644
index 0000000..afffa63
--- /dev/null
+++ b/src/components/Profile/StatCard.jsx
@@ -0,0 +1,77 @@
+import { Box, Grid, VStack, Text, Icon } from '@chakra-ui/react';
+import { motion } from 'framer-motion';
+import {
+ ChatBubbleBottomCenterTextIcon,
+ StarIcon,
+ FireIcon,
+} from '@heroicons/react/24/outline';
+import { PropTypes } from 'prop-types';
+
+const MotionBox = motion(Box);
+
+const StatItem = ({ icon, value, label }) => (
+
+
+
+ {value}
+
+
+ {label}
+
+
+);
+
+StatItem.propTypes = {
+ icon: PropTypes.elementType.isRequired,
+ value: PropTypes.number.isRequired,
+ label: PropTypes.string.isRequired,
+};
+
+const StatCard = ({ stats }) => (
+
+
+
+
+
+
+
+);
+
+StatCard.propTypes = {
+ stats: PropTypes.object.isRequired,
+};
+export default StatCard;
diff --git a/src/components/Profile/UserInfoCard.jsx b/src/components/Profile/UserInfoCard.jsx
new file mode 100644
index 0000000..c9aa664
--- /dev/null
+++ b/src/components/Profile/UserInfoCard.jsx
@@ -0,0 +1,61 @@
+import { Link } from 'react-router-dom';
+import { Box, VStack, Text, IconButton, Avatar } from '@chakra-ui/react';
+import { motion } from 'framer-motion';
+import { HiPencil } from 'react-icons/hi';
+import { PropTypes } from 'prop-types';
+
+const MotionBox = motion(Box);
+
+const UserInfoCard = ({ user }) => (
+
+ }
+ position="absolute"
+ top={4}
+ right={4}
+ colorScheme="purple"
+ variant="ghost"
+ borderRadius="full"
+ _hover={{
+ bg: 'rgba(138, 43, 226, 0.2)',
+ }}
+ />
+
+
+
+ {user?.displayName}
+
+ @{user?.uid?.slice(0, 8)}
+
+
+);
+
+UserInfoCard.propTypes = {
+ user: PropTypes.object.isRequired,
+};
+
+export default UserInfoCard;
diff --git a/src/components/ProfileEdit.jsx b/src/components/ProfileEdit.jsx
new file mode 100644
index 0000000..30a9270
--- /dev/null
+++ b/src/components/ProfileEdit.jsx
@@ -0,0 +1,201 @@
+import { useState, useEffect } from 'react';
+import { auth, db } from '../config/firebase';
+import { updateProfile, updateEmail, updatePassword } from 'firebase/auth';
+import { doc, updateDoc } from 'firebase/firestore';
+import {
+ Box,
+ Button,
+ Input,
+ Flex,
+ Avatar,
+ Select,
+ FormControl,
+ FormLabel,
+ FormErrorMessage,
+ Text,
+} from '@chakra-ui/react';
+import { motion } from 'framer-motion';
+
+const MotionBox = motion(Box);
+const MotionButton = motion(Button);
+const MotionInput = motion(Input);
+const MotionSelect = motion(Select);
+
+const ProfileEdit = () => {
+ const [username, setUsername] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [icon, setIcon] = useState('');
+ const [error, setError] = useState('');
+ const [success, setSuccess] = useState('');
+
+ const iconOptions = ['icon1.png', 'icon2.png', 'icon3.png']; // アイコンの選択肢
+
+ useEffect(() => {
+ const user = auth.currentUser;
+ if (user) {
+ setUsername(user.displayName || '');
+ setEmail(user.email || '');
+ setIcon(user.photoURL || '');
+ }
+ }, []);
+
+ const handleUpdateProfile = async () => {
+ try {
+ const user = auth.currentUser;
+ if (user) {
+ await updateProfile(user, {
+ displayName: username,
+ photoURL: icon,
+ });
+ await updateEmail(user, email);
+ if (password) {
+ await updatePassword(user, password);
+ }
+ const userDoc = doc(db, 'users', user.uid);
+ await updateDoc(userDoc, {
+ username,
+ email,
+ photoURL: icon,
+ });
+ setSuccess('プロフィールが更新されました');
+ setError(''); // 成功時はエラーメッセージをクリア
+ }
+ } catch (err) {
+ console.error(err);
+ setError('プロフィールの更新に失敗しました');
+ setSuccess(''); // 失敗時は成功メッセージをクリア
+ }
+ };
+
+ return (
+
+
+
+
+ setIcon(e.target.value)}
+ mb={4}
+ bg="rgba(255, 255, 255, 0.06)"
+ color="white"
+ _hover={{ bg: 'rgba(255, 255, 255, 0.08)' }} // commonStyles.inputHoverBg を直接指定
+ _focus={{
+ bg: 'rgba(255, 255, 255, 0.08)', // commonStyles.inputFocusBg を直接指定
+ boxShadow: '0 0 0 2px pink.400', // commonStyles.inputFocusBoxShadow を直接指定
+ borderColor: 'transparent',
+ }}
+ borderRadius="2xl" // commonStyles.borderRadius を直接指定
+ fontSize="lg" // commonStyles.fontSize を直接指定
+ fontWeight="bold" // commonStyles.fontWeight を直接指定
+ transition="all 0.3s"
+ border="1px solid rgba(255, 255, 255, 0.1)" // commonStyles.border を直接指定
+ boxShadow="0 0 30px rgba(236, 72, 153, 0.3)"
+ whileHover={{
+ scale: 1.05,
+ boxShadow: '0 0 25px rgba(236, 72, 153, 0.5)',
+ }}
+ whileTap={{ scale: 0.95 }}
+ >
+ {iconOptions.map((option) => (
+
+ ))}
+
+
+
+ {' '}
+ {/* errorがnullでない場合にisInvalidをtrueにする */}
+
+ パスワード
+
+ setPassword(e.target.value)}
+ placeholder="新しいパスワードを入力してください"
+ bg="rgba(255, 255, 255, 0.06)"
+ color="white"
+ _placeholder={{ color: 'gray.400' }}
+ _hover={{ bg: 'rgba(255, 255, 255, 0.08)' }} // commonStyles.inputHoverBg を直接指定
+ _focus={{
+ bg: 'rgba(255, 255, 255, 0.08)', // commonStyles.inputFocusBg を直接指定
+ boxShadow: '0 0 0 2px pink.400', // commonStyles.inputFocusBoxShadow を直接指定
+ borderColor: 'transparent',
+ }}
+ borderRadius="2xl" // commonStyles.borderRadius を直接指定
+ fontSize="lg" // commonStyles.fontSize を直接指定
+ fontWeight="bold" // commonStyles.fontWeight を直接指定
+ transition="all 0.3s"
+ border="1px solid rgba(255, 255, 255, 0.1)" // commonStyles.border を直接指定
+ boxShadow="0 0 30px rgba(236, 72, 153, 0.3)"
+ whileHover={{
+ scale: 1.05,
+ boxShadow: '0 0 25px rgba(236, 72, 153, 0.5)',
+ }}
+ whileTap={{ scale: 0.95 }}
+ />
+ {error}{' '}
+ {/* エラーメッセージを表示 */}
+
+ {/* ... existing code for email and password ... */}
+
+ 更新
+
+ {error && (
+
+ {error}
+
+ )}{' '}
+ {/* エラーメッセージ */}
+ {success && (
+
+ {success}
+
+ )}{' '}
+ {/* 成功メッセージ */}
+
+
+ );
+};
+
+export default ProfileEdit;
diff --git a/src/components/ProfileStyles.css b/src/components/ProfileStyles.css
new file mode 100644
index 0000000..f31cd9e
--- /dev/null
+++ b/src/components/ProfileStyles.css
@@ -0,0 +1,24 @@
+.masonry-grid {
+ display: flex;
+ width: auto;
+ margin-left: -16px;
+}
+
+.masonry-grid_column {
+ padding-left: 16px;
+ background-clip: padding-box;
+}
+
+.masonry-grid_column>div {
+ margin-bottom: 16px;
+}
+
+@media (max-width: 700px) {
+ .masonry-grid {
+ margin-left: -8px;
+ }
+
+ .masonry-grid_column {
+ padding-left: 8px;
+ }
+}
\ No newline at end of file