built with ai (cursor/claude)

tinder clone for rating bricks

16 brick images, swipe left/right functionality
match modal with profile pics auto-dismisses after 2s
background image fades in on swipe
end screen with youtube video link
styling and animations

complete joke website but functional
This commit is contained in:
Mathieu Moran
2025-12-28 04:28:01 -05:00
parent 8667fd5d84
commit 0072e57abc
23 changed files with 1240 additions and 3 deletions
+27 -3
View File
@@ -1,6 +1,30 @@
# RateMyBrick # RateMyBrick 🧱
When you don't know if your brick is fabulous. A Tinder-style app for rating bricks! Swipe right if you like a brick, left if you don't.
🧱 When you don't know if your brick is fabulous. 🧱
## Features
- Swipe cards left or right (or use buttons)
- Match animation when you like a brick
- Track your liked bricks
- Simple, clean Tinder-like UI
- No database required - uses JSON file for brick data
## How to Use
1. Open `index.html` in your web browser
2. Swipe cards left (nope) or right (like)
3. Or use the buttons at the bottom
4. See how many bricks you've liked!
## Adding More Bricks
Edit `bricks.json` or the `bricks` array in `script.js` to add more bricks. Each brick needs:
- `id`: Unique number
- `name`: Brick name
- `image`: URL to brick image or local path
- `description`: Fun description
- `color`: Brick color
- `texture`: Brick texture
+130
View File
@@ -0,0 +1,130 @@
[
{
"id": 1,
"name": "Old Brick Wall",
"image": "images/brick_01.jpg",
"description": "A moody close-up of an old brick wall with character.",
"color": "Brown",
"texture": "Weathered"
},
{
"id": 2,
"name": "Dark Brick Wall",
"image": "images/brick_02.jpg",
"description": "Close-up texture of a dark, rough brick wall.",
"color": "Dark Brown",
"texture": "Rough"
},
{
"id": 3,
"name": "White Brick Wall",
"image": "images/brick_03.jpg",
"description": "A minimalist white brick wall casting shadows.",
"color": "White",
"texture": "Smooth"
},
{
"id": 4,
"name": "Red Brick Building",
"image": "images/brick_04.jpg",
"description": "Red-brick modern building against a vibrant blue sky.",
"color": "Red",
"texture": "Modern"
},
{
"id": 5,
"name": "Weathered Red Brick",
"image": "images/brick_05.jpg",
"description": "A detailed view of a weathered red brick wall.",
"color": "Red",
"texture": "Weathered"
},
{
"id": 6,
"name": "Ancient Brick Archway",
"image": "images/brick_06.jpg",
"description": "The timeless beauty of an ancient brick archway.",
"color": "Brown",
"texture": "Aged"
},
{
"id": 7,
"name": "Vintage Brick Door",
"image": "images/brick_07.jpg",
"description": "A vintage wooden door set in historic brickwork.",
"color": "Brown",
"texture": "Vintage"
},
{
"id": 8,
"name": "Brick Archway",
"image": "images/brick_08.jpg",
"description": "Captivating brick archway showcasing architectural beauty.",
"color": "Brown",
"texture": "Textured"
},
{
"id": 9,
"name": "Ancient Stone Masonry",
"image": "images/brick_09.jpg",
"description": "Explore the timeless beauty of ancient stone masonry with a view through a historic window in ruins.",
"color": "Brown",
"texture": "Ancient"
},
{
"id": 10,
"name": "Pink Brick Wall",
"image": "images/brick_10.jpg",
"description": "Light pink textured brick wall corner perfect for backgrounds and design.",
"color": "Pink",
"texture": "Textured"
},
{
"id": 11,
"name": "Urban Brick Alley",
"image": "images/brick_11.jpg",
"description": "Explore the character of a narrow urban alley lined with rustic brick walls and faded graffiti.",
"color": "Brown",
"texture": "Rustic"
},
{
"id": 12,
"name": "Red Brick Wall",
"image": "images/brick_12.jpg",
"description": "High-resolution image of a red brick wall with white mortar lines, perfect for backgrounds.",
"color": "Red",
"texture": "Classic"
},
{
"id": 13,
"name": "Aged Brick Window",
"image": "images/brick_13.jpg",
"description": "A cat peeks through a wooden window of an aged building, adding charm.",
"color": "Brown",
"texture": "Aged"
},
{
"id": 14,
"name": "Roman Stone Arch",
"image": "images/brick_14.jpg",
"description": "Detailed view of an ancient Roman stone arch with ornate decorative carvings.",
"color": "Brown",
"texture": "Ornate"
},
{
"id": 15,
"name": "Cozy Brick Fireplace",
"image": "images/brick_15.jpg",
"description": "Cozy winter fireplace with brickwork showcasing warm textures.",
"color": "Brown",
"texture": "Cozy"
},
{
"id": 16,
"name": "Classic Brick Doorway",
"image": "images/brick_16.jpg",
"description": "A classic wooden door set in an ancient stone wall with a decorative flower wreath.",
"color": "Brown",
"texture": "Classic"
}
]
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

+167
View File
@@ -0,0 +1,167 @@
{
"total_downloaded": 16,
"source": "Pexels API",
"search_query": "brick",
"images": [
{
"id": 1,
"url": "https://images.pexels.com/photos/235986/pexels-photo-235986.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Pixabay",
"photographer_url": "https://www.pexels.com/@pixabay",
"pexels_url": "https://www.pexels.com/photo/brown-brick-wall-235986/",
"alt": "A moody close-up of an old brick wall featuring a barred window, capturing a sense of nostalgia.",
"local_path": "images\\brick_01.jpg",
"filename": "brick_01.jpg"
},
{
"id": 2,
"url": "https://images.pexels.com/photos/2273488/pexels-photo-2273488.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Orlando Allo",
"photographer_url": "https://www.pexels.com/@orlandoallo",
"pexels_url": "https://www.pexels.com/photo/brown-concrete-wall-bricks-2273488/",
"alt": "Close-up texture of a dark, rough brick wall, perfect for backgrounds.",
"local_path": "images\\brick_02.jpg",
"filename": "brick_02.jpg"
},
{
"id": 3,
"url": "https://images.pexels.com/photos/1225284/pexels-photo-1225284.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "\ud835\udddb&\ud835\uddd6\ud835\udde2 \u3000",
"photographer_url": "https://www.pexels.com/@hngstrm",
"pexels_url": "https://www.pexels.com/photo/white-brick-wall-near-white-chair-1225284/",
"alt": "A minimalist white brick wall casting a shadow, paired with a modern chair and table.",
"local_path": "images\\brick_03.jpg",
"filename": "brick_03.jpg"
},
{
"id": 4,
"url": "https://images.pexels.com/photos/1031593/pexels-photo-1031593.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Marlene Lepp\u00e4nen",
"photographer_url": "https://www.pexels.com/@marleneleppanen",
"pexels_url": "https://www.pexels.com/photo/red-and-black-concrete-high-rise-building-1031593/",
"alt": "Red-brick modern building against a vibrant blue sky and clouds.",
"local_path": "images\\brick_04.jpg",
"filename": "brick_04.jpg"
},
{
"id": 5,
"url": "https://images.pexels.com/photos/3752575/pexels-photo-3752575.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Matheus Bertelli",
"photographer_url": "https://www.pexels.com/@bertellifotografia",
"pexels_url": "https://www.pexels.com/photo/shabby-brick-wall-in-sunny-day-3752575/",
"alt": "A detailed view of a weathered red brick wall showcasing rustic textures and shadows.",
"local_path": "images\\brick_05.jpg",
"filename": "brick_05.jpg"
},
{
"id": 6,
"url": "https://images.pexels.com/photos/60573/vaulted-cellar-tunnel-arches-keller-60573.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Pixabay",
"photographer_url": "https://www.pexels.com/@pixabay",
"pexels_url": "https://www.pexels.com/photo/empty-corridor-60573/",
"alt": "Explore the timeless beauty of an ancient brick archway corridor with striking architectural design.",
"local_path": "images\\brick_06.jpg",
"filename": "brick_06.jpg"
},
{
"id": 7,
"url": "https://images.pexels.com/photos/2909959/pexels-photo-2909959.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Hisham Yahya",
"photographer_url": "https://www.pexels.com/@hishamyahyaa",
"pexels_url": "https://www.pexels.com/photo/wooden-door-of-a-bricked-wall-2909959/",
"alt": "Explore the charm of a vintage wooden door set in Erbil's historic brick architecture.",
"local_path": "images\\brick_07.jpg",
"filename": "brick_07.jpg"
},
{
"id": 8,
"url": "https://images.pexels.com/photos/2125441/pexels-photo-2125441.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Maxim Uvarov",
"photographer_url": "https://www.pexels.com/@maxim-uvarov-537292",
"pexels_url": "https://www.pexels.com/photo/woman-walking-on-concrete-hallway-2125441/",
"alt": "Captivating view of a brick archway in Tula showcasing architectural beauty and symmetry.",
"local_path": "images\\brick_08.jpg",
"filename": "brick_08.jpg"
},
{
"id": 9,
"url": "https://images.pexels.com/photos/1658591/pexels-photo-1658591.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Ralph David",
"photographer_url": "https://www.pexels.com/@rlpdavid",
"pexels_url": "https://www.pexels.com/photo/brown-rock-formation-under-blue-sky-1658591/",
"alt": "Explore the timeless beauty of ancient stone masonry with a view through a historic window in ruins.",
"local_path": "images\\brick_09.jpg",
"filename": "brick_09.jpg"
},
{
"id": 10,
"url": "https://images.pexels.com/photos/3059541/pexels-photo-3059541.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "RF._.studio _",
"photographer_url": "https://www.pexels.com/@rethaferguson",
"pexels_url": "https://www.pexels.com/photo/brick-wall-texture-3059541/",
"alt": "Light pink textured brick wall corner perfect for backgrounds and design.",
"local_path": "images\\brick_10.jpg",
"filename": "brick_10.jpg"
},
{
"id": 11,
"url": "https://images.pexels.com/photos/3703733/pexels-photo-3703733.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Lisa from Pexels",
"photographer_url": "https://www.pexels.com/@fotios-photos",
"pexels_url": "https://www.pexels.com/photo/brown-brick-building-beside-road-3703733/",
"alt": "Explore the character of a narrow urban alley lined with rustic brick walls and faded graffiti.",
"local_path": "images\\brick_11.jpg",
"filename": "brick_11.jpg"
},
{
"id": 12,
"url": "https://images.pexels.com/photos/2817481/pexels-photo-2817481.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Adrien Olichon",
"photographer_url": "https://www.pexels.com/@adrien-olichon-1257089",
"pexels_url": "https://www.pexels.com/photo/brick-wall-2817481/",
"alt": "High-resolution image of a red brick wall with white mortar lines, perfect for backgrounds.",
"local_path": "images\\brick_12.jpg",
"filename": "brick_12.jpg"
},
{
"id": 13,
"url": "https://images.pexels.com/photos/35381909/pexels-photo-35381909.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Anadolu g\u00fcncesi",
"photographer_url": "https://www.pexels.com/@anadolu-guncesi-1485592294",
"pexels_url": "https://www.pexels.com/photo/rustic-window-with-curious-cat-35381909/",
"alt": "A cat peeks through a wooden window of an aged building, adding charm.",
"local_path": "images\\brick_13.jpg",
"filename": "brick_13.jpg"
},
{
"id": 14,
"url": "https://images.pexels.com/photos/35381803/pexels-photo-35381803.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "lumverte",
"photographer_url": "https://www.pexels.com/@lumverte",
"pexels_url": "https://www.pexels.com/photo/ancient-roman-arch-with-decorative-carvings-35381803/",
"alt": "Detailed view of an ancient Roman stone arch with ornate decorative carvings.",
"local_path": "images\\brick_14.jpg",
"filename": "brick_14.jpg"
},
{
"id": 15,
"url": "https://images.pexels.com/photos/35367981/pexels-photo-35367981.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Cansu Hang\u00fcl",
"photographer_url": "https://www.pexels.com/@cansu-hangul-464804780",
"pexels_url": "https://www.pexels.com/photo/cozy-winter-fireplace-with-coffee-and-tablet-35367981/",
"alt": "Free stock photo of creativeworkshop, hyggevibes, seramiksanat\u0131",
"local_path": "images\\brick_15.jpg",
"filename": "brick_15.jpg"
},
{
"id": 16,
"url": "https://images.pexels.com/photos/923023/pexels-photo-923023.jpeg?auto=compress&cs=tinysrgb&h=650&w=940",
"photographer": "Fredrik Rubensson",
"photographer_url": "https://www.pexels.com/@fredrik-rubensson-328486",
"pexels_url": "https://www.pexels.com/photo/closed-brown-wooden-door-923023/",
"alt": "A classic wooden door set in an ancient stone wall with a decorative flower wreath.",
"local_path": "images\\brick_16.jpg",
"filename": "brick_16.jpg"
}
]
}
+96
View File
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RateMyBrick - Swipe on Bricks!</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🧱</text></svg>">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="app-container">
<header>
<h1>🧱 RateMyBrick</h1>
<p class="subtitle">Swipe right if you like the brick, left if you don't</p>
</header>
<div class="card-container" id="cardContainer">
<div class="background-image-container">
<img src="images/background.jpg" alt="" class="background-image">
</div>
<div class="card" id="currentCard">
<div class="card-image-container">
<img id="brickImage" src="" alt="Brick">
<div class="card-overlay">
<div class="like-badge">LIKE</div>
<div class="nope-badge">NOPE</div>
</div>
</div>
<div class="card-info">
<h2 id="brickName"></h2>
<p id="brickDescription"></p>
<div class="brick-stats">
<span id="brickColor"></span>
<span id="brickTexture"></span>
</div>
</div>
</div>
</div>
<div class="actions">
<button class="action-btn nope-btn" id="nopeBtn">
<span>✕</span>
</button>
<button class="action-btn like-btn" id="likeBtn">
<span>♥</span>
</button>
</div>
<div class="stats">
<div class="stat-item">
<span class="stat-label">Liked:</span>
<span class="stat-value" id="likedCount">0</span>
</div>
<div class="stat-item">
<span class="stat-label">Remaining:</span>
<span class="stat-value" id="remainingCount">0</span>
</div>
</div>
<div class="match-popup" id="matchPopup">
<div class="match-content">
<h2>It's a Match! 🧱</h2>
<div class="match-profiles">
<div class="profile-picture left-profile">
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fmedia.istockphoto.com%2Fid%2F184374333%2Fphoto%2Fcommon-house-brick.jpg%3Fs%3D612x612%26w%3D0%26k%3D20%26c%3D4P9EPMx6VNtTM6pmKY2N4hHQDACcVfylceJh5xrAcS4%3D&f=1&nofb=1&ipt=0e97069ed75431afcb0ab3f13d4c15e2fa92646092dd989e49f5e39d1a713c2d" alt="Brick" id="leftProfileImg">
</div>
<div class="profile-picture right-profile">
<img src="" alt="Brick" id="rightProfileImg">
</div>
</div>
<p>You liked this brick!</p>
</div>
</div>
<div class="end-screen" id="endScreen">
<h2>You've seen all the bricks! 🧱</h2>
<p>You liked <span id="finalLikedCount">0</span> bricks</p>
<div class="video-container">
<a href="https://www.youtube.com/watch?v=en-dhgSLddI&autoplay=1" target="_blank" class="video-link-container">
<img src="https://img.youtube.com/vi/en-dhgSLddI/maxresdefault.jpg" alt="Video thumbnail" class="video-thumbnail">
<div class="play-button">
<svg width="68" height="48" viewBox="0 0 68 48">
<path d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.63-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f00"></path>
<path d="M 45,24 27,14 27,34" fill="#fff"></path>
</svg>
</div>
</a>
</div>
<button class="restart-btn" id="restartBtn">Start Over</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
+357
View File
@@ -0,0 +1,357 @@
// Brick data - loaded from Pexels API downloads
const bricks = [
{
id: 1,
name: "Old Brick Wall",
image: "images/brick_01.jpg",
description: "A moody close-up of an old brick wall with character.",
color: "Brown",
texture: "Weathered"
},
{
id: 2,
name: "Dark Brick Wall",
image: "images/brick_02.jpg",
description: "Close-up texture of a dark, rough brick wall.",
color: "Dark Brown",
texture: "Rough"
},
{
id: 3,
name: "White Brick Wall",
image: "images/brick_03.jpg",
description: "A minimalist white brick wall casting shadows.",
color: "White",
texture: "Smooth"
},
{
id: 4,
name: "Red Brick Building",
image: "images/brick_04.jpg",
description: "Red-brick modern building against a vibrant blue sky.",
color: "Red",
texture: "Modern"
},
{
id: 5,
name: "Weathered Red Brick",
image: "images/brick_05.jpg",
description: "A detailed view of a weathered red brick wall.",
color: "Red",
texture: "Weathered"
},
{
id: 6,
name: "Ancient Brick Archway",
image: "images/brick_06.jpg",
description: "The timeless beauty of an ancient brick archway.",
color: "Brown",
texture: "Aged"
},
{
id: 7,
name: "Vintage Brick Door",
image: "images/brick_07.jpg",
description: "A vintage wooden door set in historic brickwork.",
color: "Brown",
texture: "Vintage"
},
{
id: 8,
name: "Brick Archway",
image: "images/brick_08.jpg",
description: "Captivating brick archway showcasing architectural beauty.",
color: "Brown",
texture: "Textured"
},
{
id: 9,
name: "Ancient Stone Masonry",
image: "images/brick_09.jpg",
description: "Explore the timeless beauty of ancient stone masonry with a view through a historic window in ruins.",
color: "Brown",
texture: "Ancient"
},
{
id: 10,
name: "Pink Brick Wall",
image: "images/brick_10.jpg",
description: "Light pink textured brick wall corner perfect for backgrounds and design.",
color: "Pink",
texture: "Textured"
},
{
id: 11,
name: "Urban Brick Alley",
image: "images/brick_11.jpg",
description: "Explore the character of a narrow urban alley lined with rustic brick walls and faded graffiti.",
color: "Brown",
texture: "Rustic"
},
{
id: 12,
name: "Red Brick Wall",
image: "images/brick_12.jpg",
description: "High-resolution image of a red brick wall with white mortar lines, perfect for backgrounds.",
color: "Red",
texture: "Classic"
},
{
id: 13,
name: "Aged Brick Window",
image: "images/brick_13.jpg",
description: "A cat peeks through a wooden window of an aged building, adding charm.",
color: "Brown",
texture: "Aged"
},
{
id: 14,
name: "Roman Stone Arch",
image: "images/brick_14.jpg",
description: "Detailed view of an ancient Roman stone arch with ornate decorative carvings.",
color: "Brown",
texture: "Ornate"
},
{
id: 15,
name: "Cozy Brick Fireplace",
image: "images/brick_15.jpg",
description: "Cozy winter fireplace with brickwork showcasing warm textures.",
color: "Brown",
texture: "Cozy"
},
{
id: 16,
name: "Classic Brick Doorway",
image: "images/brick_16.jpg",
description: "A classic wooden door set in an ancient stone wall with a decorative flower wreath.",
color: "Brown",
texture: "Classic"
}
];
let currentIndex = 0;
let likedCount = 0;
let startX = 0;
let startY = 0;
let currentX = 0;
let currentY = 0;
let isDragging = false;
const card = document.getElementById('currentCard');
const brickImage = document.getElementById('brickImage');
const brickName = document.getElementById('brickName');
const brickDescription = document.getElementById('brickDescription');
const brickColor = document.getElementById('brickColor');
const brickTexture = document.getElementById('brickTexture');
const likeBtn = document.getElementById('likeBtn');
const nopeBtn = document.getElementById('nopeBtn');
const likedCountEl = document.getElementById('likedCount');
const remainingCountEl = document.getElementById('remainingCount');
const endScreen = document.getElementById('endScreen');
const finalLikedCount = document.getElementById('finalLikedCount');
const restartBtn = document.getElementById('restartBtn');
const backgroundImage = document.querySelector('.background-image');
const matchPopup = document.getElementById('matchPopup');
function loadBrick(index) {
if (index >= bricks.length) {
showEndScreen();
return;
}
const brick = bricks[index];
// Reset card position and opacity for smooth entry
card.style.transition = 'none';
card.style.transform = 'translate(0, 0) rotate(0deg)';
card.style.opacity = '0';
// Hide background image when new card loads
if (backgroundImage) {
backgroundImage.style.transition = 'opacity 0.3s ease-in';
backgroundImage.style.opacity = '0';
}
// Update content
brickImage.src = brick.image;
brickImage.alt = brick.name;
brickName.textContent = brick.name;
brickDescription.textContent = brick.description;
brickColor.textContent = brick.color;
brickTexture.textContent = brick.texture;
card.querySelector('.card-overlay').classList.remove('active');
updateStats();
// Fade in the new card smoothly
setTimeout(() => {
card.style.transition = 'opacity 0.3s ease-in';
card.style.opacity = '1';
}, 50);
}
function updateStats() {
likedCountEl.textContent = likedCount;
remainingCountEl.textContent = bricks.length - currentIndex;
}
function swipeCard(direction) {
const overlay = card.querySelector('.card-overlay');
const likeBadge = overlay.querySelector('.like-badge');
const nopeBadge = overlay.querySelector('.nope-badge');
overlay.classList.add('active');
// Set transition for smooth animation
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
// Show background image as card swipes away
if (backgroundImage) {
backgroundImage.style.transition = 'opacity 0.4s ease-out';
backgroundImage.style.opacity = '0.10';
}
if (direction === 'right') {
likeBadge.style.display = 'block';
nopeBadge.style.display = 'none';
likedCount++;
updateStats();
// Smoothly animate card off screen
card.style.transform = `translate(400px, 0) rotate(25deg)`;
card.style.opacity = '0';
// Show match popup after card animation, then auto-continue
setTimeout(() => {
showMatchPopup();
// Auto-hide and continue after 2 seconds
setTimeout(() => {
hideMatchPopup();
nextBrick();
}, 2000);
}, 400);
} else {
nopeBadge.style.display = 'block';
likeBadge.style.display = 'none';
// Smoothly animate card off screen
card.style.transform = `translate(-400px, 0) rotate(-25deg)`;
card.style.opacity = '0';
// Load next brick after animation completes
setTimeout(() => {
nextBrick();
}, 400);
}
}
function showMatchPopup() {
if (matchPopup) {
// Set the right profile image to the current brick
const rightProfileImg = document.getElementById('rightProfileImg');
if (rightProfileImg && currentIndex < bricks.length) {
rightProfileImg.src = bricks[currentIndex].image;
}
matchPopup.classList.add('show');
}
}
function hideMatchPopup() {
if (matchPopup) {
matchPopup.classList.remove('show');
}
}
function nextBrick() {
currentIndex++;
loadBrick(currentIndex);
}
function showEndScreen() {
endScreen.classList.add('show');
finalLikedCount.textContent = likedCount;
}
function restart() {
currentIndex = 0;
likedCount = 0;
endScreen.classList.remove('show');
loadBrick(0);
}
// Touch/Mouse events for swiping
card.addEventListener('mousedown', startDrag);
card.addEventListener('touchstart', startDrag);
card.addEventListener('mousemove', drag);
card.addEventListener('touchmove', drag);
card.addEventListener('mouseup', endDrag);
card.addEventListener('touchend', endDrag);
card.addEventListener('mouseleave', endDrag);
function startDrag(e) {
isDragging = true;
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
startX = clientX - card.offsetLeft;
startY = clientY - card.offsetTop;
card.style.transition = 'none';
}
function drag(e) {
if (!isDragging) return;
e.preventDefault();
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
currentX = clientX - startX;
currentY = clientY - startY;
const rotate = currentX / 20;
card.style.transform = `translate(${currentX}px, ${currentY}px) rotate(${rotate}deg)`;
const overlay = card.querySelector('.card-overlay');
if (Math.abs(currentX) > 50) {
overlay.classList.add('active');
if (currentX > 0) {
overlay.querySelector('.like-badge').style.display = 'block';
overlay.querySelector('.nope-badge').style.display = 'none';
} else {
overlay.querySelector('.nope-badge').style.display = 'block';
overlay.querySelector('.like-badge').style.display = 'none';
}
} else {
overlay.classList.remove('active');
}
}
function endDrag() {
if (!isDragging) return;
isDragging = false;
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
if (Math.abs(currentX) > 100) {
if (currentX > 0) {
swipeCard('right');
} else {
swipeCard('left');
}
} else {
card.style.transform = 'translate(0, 0) rotate(0deg)';
card.style.opacity = '1';
card.querySelector('.card-overlay').classList.remove('active');
}
currentX = 0;
currentY = 0;
}
// Button events
likeBtn.addEventListener('click', () => swipeCard('right'));
nopeBtn.addEventListener('click', () => swipeCard('left'));
restartBtn.addEventListener('click', restart);
// Initialize
loadBrick(0);
+463
View File
@@ -0,0 +1,463 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.app-container {
width: 100%;
max-width: 400px;
position: relative;
}
header {
text-align: center;
color: white;
margin-bottom: 20px;
}
header h1 {
font-size: 2.5em;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.subtitle {
font-size: 0.9em;
opacity: 0.9;
}
.card-container {
position: relative;
height: 600px;
margin-bottom: 20px;
}
.background-image-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 75%;
max-width: 300px;
z-index: 0;
overflow: hidden;
border-radius: 10px;
pointer-events: none;
}
.background-image {
width: 100%;
height: auto;
display: block;
opacity: 0;
transition: opacity 0.4s ease-out;
}
.card {
position: absolute;
width: 100%;
height: 100%;
background: white;
border-radius: 20px;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
overflow: hidden;
cursor: grab;
user-select: none;
transition: transform 0.4s ease-out, opacity 0.4s ease-out;
opacity: 1;
z-index: 1;
}
.card:active {
cursor: grabbing;
}
.card-image-container {
width: 100%;
height: 65%;
position: relative;
overflow: hidden;
background: #f0f0f0;
}
.card-image-container img {
width: 100%;
height: 100%;
object-fit: cover;
}
.card-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
}
.card-overlay.active {
opacity: 1;
}
.like-badge, .nope-badge {
position: absolute;
top: 50px;
padding: 10px 30px;
border: 4px solid;
border-radius: 10px;
font-size: 2em;
font-weight: bold;
transform: rotate(-20deg);
text-transform: uppercase;
letter-spacing: 2px;
}
.like-badge {
right: 20px;
color: #4ade80;
border-color: #4ade80;
background: rgba(74, 222, 128, 0.1);
}
.nope-badge {
left: 20px;
color: #f87171;
border-color: #f87171;
background: rgba(248, 113, 113, 0.1);
}
.card-info {
padding: 20px;
height: 35%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.card-info h2 {
font-size: 1.8em;
color: #333;
margin-bottom: 10px;
}
.card-info p {
color: #666;
font-size: 1em;
line-height: 1.5;
margin-bottom: 15px;
}
.brick-stats {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.brick-stats span {
background: #f0f0f0;
padding: 5px 15px;
border-radius: 20px;
font-size: 0.9em;
color: #555;
}
.actions {
display: flex;
justify-content: center;
gap: 30px;
margin-bottom: 20px;
}
.action-btn {
width: 60px;
height: 60px;
border-radius: 50%;
border: none;
font-size: 1.5em;
cursor: pointer;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
transition: transform 0.2s, box-shadow 0.2s;
display: flex;
align-items: center;
justify-content: center;
}
.action-btn:active {
transform: scale(0.9);
}
.nope-btn {
background: white;
color: #f87171;
}
.nope-btn:hover {
background: #fee2e2;
box-shadow: 0 6px 20px rgba(248, 113, 113, 0.4);
}
.like-btn {
background: white;
color: #4ade80;
}
.like-btn:hover {
background: #dcfce7;
box-shadow: 0 6px 20px rgba(74, 222, 128, 0.4);
}
.stats {
display: flex;
justify-content: space-around;
background: rgba(255, 255, 255, 0.2);
padding: 15px;
border-radius: 15px;
color: white;
backdrop-filter: blur(10px);
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 5px;
}
.stat-label {
font-size: 0.9em;
opacity: 0.9;
}
.stat-value {
font-size: 1.5em;
font-weight: bold;
}
.restart-btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 1em;
cursor: pointer;
font-weight: bold;
transition: transform 0.2s;
}
.restart-btn:hover {
transform: scale(1.05);
}
.end-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
border-radius: 20px;
display: none;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
text-align: center;
z-index: 100;
overflow-y: auto;
}
.end-screen.show {
display: flex;
}
.match-popup {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: none;
justify-content: center;
align-items: center;
z-index: 1000;
transition: opacity 0.3s ease;
opacity: 0;
}
.match-popup.show {
display: flex;
opacity: 1;
}
.match-content {
background: white;
padding: 40px;
border-radius: 20px;
text-align: center;
box-shadow: 0 10px 40px rgba(0,0,0,0.3);
animation: scaleIn 0.3s ease, scaleOut 0.3s ease 1.7s;
max-width: 400px;
}
@keyframes scaleIn {
from {
transform: scale(0.8);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
@keyframes scaleOut {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(0.8);
opacity: 0;
}
}
.match-content h2 {
font-size: 2em;
color: #667eea;
margin-bottom: 25px;
}
.match-profiles {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
margin-bottom: 25px;
}
.profile-picture {
width: 120px;
height: 120px;
border-radius: 50%;
overflow: hidden;
border: 4px solid #667eea;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
animation: profilePop 0.5s ease 0.2s both;
}
.profile-picture.left-profile {
animation-delay: 0.2s;
}
.profile-picture.right-profile {
animation-delay: 0.3s;
}
@keyframes profilePop {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
.profile-picture img {
width: 100%;
height: 100%;
object-fit: cover;
}
.match-content p {
font-size: 1.2em;
color: #666;
}
.end-screen h2 {
font-size: 2em;
color: #333;
margin-bottom: 20px;
}
.end-screen p {
font-size: 1.2em;
color: #666;
margin-bottom: 30px;
}
#finalLikedCount {
font-weight: bold;
color: #667eea;
font-size: 1.5em;
}
.video-container {
width: 100%;
max-width: 560px;
margin: 20px 0 30px 0;
position: relative;
border-radius: 12px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
overflow: hidden;
}
.video-link-container {
display: block;
position: relative;
width: 100%;
padding-bottom: 56.25%; /* 16:9 aspect ratio */
overflow: hidden;
cursor: pointer;
transition: transform 0.2s;
}
.video-link-container:hover {
transform: scale(1.02);
}
.video-thumbnail {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
.play-button {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 68px;
height: 48px;
background: rgba(0,0,0,0.8);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
transition: transform 0.2s, background 0.2s;
}
.video-link-container:hover .play-button {
transform: translate(-50%, -50%) scale(1.1);
background: rgba(255,0,0,0.9);
}