diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..19ebc49
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,127 @@
+body {
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ background-color: #f4f7f6;
+ color: #333;
+ line-height: 1.6;
+}
+
+.navbar {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e7e7e7;
+ padding: 1rem 2rem;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.navbar-brand {
+ font-weight: bold;
+ font-size: 1.5rem;
+ color: #007bff;
+}
+
+.nav-links a {
+ color: #555;
+ text-decoration: none;
+ margin-left: 1.5rem;
+ font-size: 1rem;
+}
+
+.nav-links a:hover {
+ color: #007bff;
+}
+
+.container {
+ max-width: 960px;
+ margin: 2rem auto;
+ padding: 0 1rem;
+}
+
+.card {
+ background-color: #ffffff;
+ border: 1px solid #e7e7e7;
+ border-radius: 8px;
+ padding: 1.5rem;
+ margin-bottom: 1.5rem;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+}
+
+.card-title {
+ font-size: 1.25rem;
+ font-weight: bold;
+}
+
+.card-meta {
+ font-size: 0.9rem;
+ color: #777;
+}
+
+.card-body p {
+ margin-bottom: 1rem;
+}
+
+.form-control {
+ width: 100%;
+ padding: 0.75rem;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ margin-bottom: 1rem;
+}
+
+.btn {
+ display: inline-block;
+ padding: 0.75rem 1.5rem;
+ border-radius: 4px;
+ text-decoration: none;
+ font-weight: bold;
+ text-align: center;
+ cursor: pointer;
+}
+
+.btn-primary {
+ background-color: #007bff;
+ color: #ffffff;
+ border: 1px solid #007bff;
+}
+
+.btn-primary:hover {
+ background-color: #0056b3;
+}
+
+.btn-secondary {
+ background-color: #6c757d;
+ color: #ffffff;
+ border: 1px solid #6c757d;
+}
+
+.footer {
+ text-align: center;
+ padding: 2rem 0;
+ margin-top: 2rem;
+ font-size: 0.9rem;
+ color: #777;
+}
+
+/* Vote buttons */
+.vote-buttons {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+}
+
+.like-button, .dislike-button {
+ background: none;
+ border: none;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 1rem;
+}
\ No newline at end of file
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..ef67a6a
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,27 @@
+
+document.addEventListener('DOMContentLoaded', function() {
+ const voteButtons = document.querySelectorAll('.vote-buttons a');
+
+ voteButtons.forEach(button => {
+ button.addEventListener('click', function(e) {
+ e.preventDefault();
+ const url = this.href;
+ const likeCountSpan = this.querySelector('span');
+ const dislikeButton = this.parentElement.querySelector('.dislike-button');
+ const dislikeCountSpan = dislikeButton.querySelector('span');
+
+ fetch(url)
+ .then(response => response.json())
+ .then(data => {
+ if (data.success) {
+ likeCountSpan.textContent = data.likes;
+ dislikeCountSpan.textContent = data.dislikes;
+ } else {
+ // Handle errors if needed
+ console.error(data.error);
+ }
+ })
+ .catch(error => console.error('Error:', error));
+ });
+ });
+});
diff --git a/db/migrate.php b/db/migrate.php
new file mode 100644
index 0000000..375229d
--- /dev/null
+++ b/db/migrate.php
@@ -0,0 +1,22 @@
+exec($sql);
+ echo "Success.\n";
+ } catch (PDOException $e) {
+ die("Migration failed: " . $e->getMessage());
+ }
+ }
+}
+
+apply_migrations();
+
diff --git a/db/migrations/001_create_users_and_skills_tables.sql b/db/migrations/001_create_users_and_skills_tables.sql
new file mode 100644
index 0000000..68e6c93
--- /dev/null
+++ b/db/migrations/001_create_users_and_skills_tables.sql
@@ -0,0 +1,18 @@
+CREATE TABLE IF NOT EXISTS users (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ username VARCHAR(50) NOT NULL UNIQUE,
+ email VARCHAR(100) NOT NULL UNIQUE,
+ password_hash VARCHAR(255) NOT NULL,
+ display_name VARCHAR(50),
+ description TEXT,
+ occupation VARCHAR(100),
+ location VARCHAR(255),
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+CREATE TABLE IF NOT EXISTS skills (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ user_id INT NOT NULL,
+ skill_name VARCHAR(100) NOT NULL,
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/db/migrations/002_create_posts_table.sql b/db/migrations/002_create_posts_table.sql
new file mode 100644
index 0000000..081ea68
--- /dev/null
+++ b/db/migrations/002_create_posts_table.sql
@@ -0,0 +1,7 @@
+CREATE TABLE IF NOT EXISTS posts (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ user_id INT NOT NULL,
+ content TEXT NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (user_id) REFERENCES users(id)
+);
diff --git a/db/migrations/003_add_likes_to_posts.sql b/db/migrations/003_add_likes_to_posts.sql
new file mode 100644
index 0000000..22dc2f9
--- /dev/null
+++ b/db/migrations/003_add_likes_to_posts.sql
@@ -0,0 +1 @@
+ALTER TABLE posts ADD COLUMN likes INT DEFAULT 0, ADD COLUMN dislikes INT DEFAULT 0;
\ No newline at end of file
diff --git a/db/migrations/004_create_post_votes_table.sql b/db/migrations/004_create_post_votes_table.sql
new file mode 100644
index 0000000..85751b5
--- /dev/null
+++ b/db/migrations/004_create_post_votes_table.sql
@@ -0,0 +1,10 @@
+CREATE TABLE IF NOT EXISTS post_votes (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ user_id INT NOT NULL,
+ post_id INT NOT NULL,
+ vote_type ENUM('like', 'dislike') NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ UNIQUE KEY user_post_vote (user_id, post_id),
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
+ FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE
+);
diff --git a/db/migrations/005_add_city_country_to_users.sql b/db/migrations/005_add_city_country_to_users.sql
new file mode 100644
index 0000000..f7fbc82
--- /dev/null
+++ b/db/migrations/005_add_city_country_to_users.sql
@@ -0,0 +1,4 @@
+ALTER TABLE users
+ADD COLUMN city VARCHAR(100),
+ADD COLUMN country VARCHAR(100),
+DROP COLUMN location;
diff --git a/db/migrations/006_remove_likes_from_posts.sql b/db/migrations/006_remove_likes_from_posts.sql
new file mode 100644
index 0000000..b9b3650
--- /dev/null
+++ b/db/migrations/006_remove_likes_from_posts.sql
@@ -0,0 +1,3 @@
+ALTER TABLE posts
+DROP COLUMN likes,
+DROP COLUMN dislikes;
diff --git a/db/migrations/007_change_vote_type_to_int.sql b/db/migrations/007_change_vote_type_to_int.sql
new file mode 100644
index 0000000..5da8df3
--- /dev/null
+++ b/db/migrations/007_change_vote_type_to_int.sql
@@ -0,0 +1,2 @@
+ALTER TABLE post_votes
+CHANGE COLUMN vote_type vote INT NOT NULL;
diff --git a/handle_create_post.php b/handle_create_post.php
new file mode 100644
index 0000000..c15dd09
--- /dev/null
+++ b/handle_create_post.php
@@ -0,0 +1,26 @@
+prepare('INSERT INTO posts (user_id, content) VALUES (?, ?)');
+ $stmt->execute([$user_id, $content]);
+ set_flash_message('Post created successfully!', 'success');
+ } catch (PDOException $e) {
+ error_log("Failed to create post: " . $e->getMessage());
+ set_flash_message('Failed to create post. Please try again.', 'danger');
+ }
+ } else {
+ set_flash_message('Post content cannot be empty.', 'danger');
+ }
+}
+
+header("Location: index.php");
+exit;
diff --git a/handle_like.php b/handle_like.php
new file mode 100644
index 0000000..6a79310
--- /dev/null
+++ b/handle_like.php
@@ -0,0 +1,63 @@
+ false, 'error' => 'User not logged in.']);
+ exit();
+}
+
+if (!isset($_GET['post_id']) || !isset($_GET['action'])) {
+ echo json_encode(['success' => false, 'error' => 'Invalid request.']);
+ exit();
+}
+
+$postId = (int)$_GET['post_id'];
+$action = $_GET['action'];
+$userId = $_SESSION['user_id'];
+$vote = ($action === 'like') ? 1 : -1;
+
+$pdo = db();
+
+try {
+ $pdo->beginTransaction();
+
+ // Check for existing vote
+ $stmt = $pdo->prepare('SELECT vote FROM post_votes WHERE user_id = :user_id AND post_id = :post_id');
+ $stmt->execute(['user_id' => $userId, 'post_id' => $postId]);
+ $existingVote = $stmt->fetchColumn();
+
+ if ($existingVote) {
+ if ($existingVote == $vote) {
+ // User is undoing their vote
+ $stmt = $pdo->prepare('DELETE FROM post_votes WHERE user_id = :user_id AND post_id = :post_id');
+ $stmt->execute(['user_id' => $userId, 'post_id' => $postId]);
+ } else {
+ // User is changing their vote
+ $stmt = $pdo->prepare('UPDATE post_votes SET vote = :vote WHERE user_id = :user_id AND post_id = :post_id');
+ $stmt->execute(['vote' => $vote, 'user_id' => $userId, 'post_id' => $postId]);
+ }
+ } else {
+ // New vote
+ $stmt = $pdo->prepare('INSERT INTO post_votes (user_id, post_id, vote) VALUES (:user_id, :post_id, :vote)');
+ $stmt->execute(['user_id' => $userId, 'post_id' => $postId, 'vote' => $vote]);
+ }
+
+ $pdo->commit();
+
+ // Fetch new like/dislike counts
+ $stmt = $pdo->prepare('SELECT
+ (SELECT COUNT(*) FROM post_votes WHERE post_id = :post_id AND vote = 1) as likes,
+ (SELECT COUNT(*) FROM post_votes WHERE post_id = :post_id AND vote = -1) as dislikes
+ ');
+ $stmt->execute(['post_id' => $postId]);
+ $counts = $stmt->fetch(PDO::FETCH_ASSOC);
+
+ echo json_encode(['success' => true, 'likes' => $counts['likes'], 'dislikes' => $counts['dislikes']]);
+
+} catch (Exception $e) {
+ $pdo->rollBack();
+ echo json_encode(['success' => false, 'error' => 'Database error: ' . $e->getMessage()]);
+}
\ No newline at end of file
diff --git a/handle_login.php b/handle_login.php
new file mode 100644
index 0000000..a0d2e30
--- /dev/null
+++ b/handle_login.php
@@ -0,0 +1,32 @@
+prepare('SELECT id, password_hash FROM users WHERE email = ?');
+ $stmt->execute([$email]);
+ $user = $stmt->fetch();
+
+ if ($user && password_verify($password, $user['password_hash'])) {
+ $_SESSION['user_id'] = $user['id'];
+ set_flash_message('You have been successfully logged in.', 'success');
+ header("Location: index.php");
+ exit;
+ } else {
+ set_flash_message('Invalid email or password.', 'danger');
+ header("Location: login.php");
+ exit;
+ }
+ } catch (PDOException $e) {
+ set_flash_message('Database error. Please try again.', 'danger');
+ error_log("Login DB Error: " . $e->getMessage());
+ header("Location: login.php");
+ exit;
+ }
+}
diff --git a/handle_profile_setup.php b/handle_profile_setup.php
new file mode 100644
index 0000000..08dbb96
--- /dev/null
+++ b/handle_profile_setup.php
@@ -0,0 +1,70 @@
+prepare(
+ "UPDATE users SET display_name = ?, description = ?, occupation = ?, city = ?, country = ? WHERE id = ?"
+ );
+ $stmt->execute([$displayName, $description, $occupation, $city, $country, $userId]);
+
+ // Handle skills
+ $skills = json_decode($skillsJson, true);
+
+ if (is_array($skills) && !empty($skills)) {
+ // First, remove existing skills for the user to prevent duplicates on re-editing
+ $deleteStmt = $pdo->prepare("DELETE FROM skills WHERE user_id = ?");
+ $deleteStmt->execute([$userId]);
+
+ // Insert new skills
+ $insertStmt = $pdo->prepare("INSERT INTO skills (user_id, skill_name) VALUES (?, ?)");
+ foreach ($skills as $skill) {
+ if (!empty(trim($skill))) {
+ $insertStmt->execute([$userId, trim($skill)]);
+ }
+ }
+ }
+
+ set_flash_message('Profile updated successfully!', 'success');
+ // Redirect to a success page or the main feed
+ header('Location: profile.php?id=' . $userId);
+ exit();
+
+ } catch (PDOException $e) {
+ set_flash_message('Database error: ' . $e->getMessage(), 'danger');
+ header('Location: profile_setup.php');
+ exit();
+ }
+
+} else {
+ // If not a POST request, redirect away
+ header('Location: profile_setup.php');
+ exit();
+}
+?>
diff --git a/handle_signup.php b/handle_signup.php
new file mode 100644
index 0000000..3d54630
--- /dev/null
+++ b/handle_signup.php
@@ -0,0 +1,68 @@
+prepare("SELECT id FROM users WHERE username = ? OR email = ?");
+$stmt->execute([$username, $email]);
+if ($stmt->fetch()) {
+ set_flash_message('Username or email already exists.', 'danger');
+ header('Location: signup.php');
+ exit();
+}
+
+// --- Create User ---
+$password_hash = password_hash($password, PASSWORD_DEFAULT);
+
+$stmt = $pdo->prepare("INSERT INTO users (username, email, password_hash, display_name) VALUES (?, ?, ?, ?)");
+try {
+ $stmt->execute([$username, $email, $password_hash, $username]);
+ $user_id = $pdo->lastInsertId();
+
+ // Log the user in
+ $_SESSION['user_id'] = $user_id;
+ $_SESSION['username'] = $username;
+
+ set_flash_message('You have successfully registered. Please complete your profile.', 'success');
+ // Redirect to profile setup
+ header('Location: profile_setup.php');
+ exit();
+
+} catch (PDOException $e) {
+ set_flash_message('Database error. Please try again.', 'danger');
+ error_log("Signup DB Error: " . $e->getMessage());
+ header('Location: signup.php');
+ exit();
+}
diff --git a/includes/flash_messages.php b/includes/flash_messages.php
new file mode 100644
index 0000000..53763da
--- /dev/null
+++ b/includes/flash_messages.php
@@ -0,0 +1,17 @@
+ $message,
+ 'type' => $type
+ ];
+}
+
+function display_flash_message() {
+ if (isset($_SESSION['flash_message'])) {
+ $message = $_SESSION['flash_message']['message'];
+ $type = $_SESSION['flash_message']['type'];
+ unset($_SESSION['flash_message']);
+ echo "
{$message}
";
+ }
+}
diff --git a/index.php b/index.php
index 7205f3d..e3841d0 100644
--- a/index.php
+++ b/index.php
@@ -1,150 +1,111 @@
query('
+ SELECT
+ posts.id,
+ posts.content,
+ posts.created_at,
+ users.display_name,
+ users.id as user_id,
+ (SELECT COUNT(*) FROM post_votes WHERE post_id = posts.id AND vote = 1) as likes,
+ (SELECT COUNT(*) FROM post_votes WHERE post_id = posts.id AND vote = -1) as dislikes
+ FROM posts
+ JOIN users ON posts.user_id = users.id
+ ORDER BY posts.created_at DESC
+ ');
+ $posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
+} catch (PDOException $e) {
+ // Handle database errors gracefully
+ error_log("DB Error: " . $e->getMessage());
+}
-$phpVersion = PHP_VERSION;
-$now = date('Y-m-d H:i:s');
?>
-
+
-
-
- New Style
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ Welcome to Our Social Platform
+
+
-
-
-
Analyzing your requirements and generating your website…
-
- Loading…
-
-
= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.
-
This page will update automatically as the plan is implemented.
-
Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
+
+
+
+
+
+
+
+
+
Feed
+
+
No posts yet. Be the first to share!
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
-
+