diff --git a/db/sccharacters.php b/db/sccharacters.php index 9b8817b..d5ecbb5 100644 --- a/db/sccharacters.php +++ b/db/sccharacters.php @@ -56,6 +56,7 @@ function sccharacters_bootstrap(): void cl_sccharacter_notes TEXT DEFAULT NULL, cl_sccharacter_share_token VARCHAR(64) NOT NULL, cl_sccharacter_share_enabled TINYINT(1) NOT NULL DEFAULT 0, + cl_sccharacter_is_pinned TINYINT(1) NOT NULL DEFAULT 0, cl_sccharacter_category_order TEXT DEFAULT NULL, cl_sccharacter_created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, cl_sccharacter_updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, @@ -91,10 +92,17 @@ function sccharacters_bootstrap(): void ); } + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_is_pinned')) { + $db->exec( + 'ALTER TABLE tbl_sccharacters + ADD COLUMN cl_sccharacter_is_pinned TINYINT(1) NOT NULL DEFAULT 0 AFTER cl_sccharacter_share_enabled' + ); + } + if (!sccharacters_column_exists($db, 'tbl_sccharacters', 'cl_sccharacter_category_order')) { $db->exec( 'ALTER TABLE tbl_sccharacters - ADD COLUMN cl_sccharacter_category_order TEXT NULL AFTER cl_sccharacter_share_enabled' + ADD COLUMN cl_sccharacter_category_order TEXT NULL AFTER cl_sccharacter_is_pinned' ); } diff --git a/sccharacters.php b/sccharacters.php index d177169..f44d1f7 100644 --- a/sccharacters.php +++ b/sccharacters.php @@ -790,6 +790,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $description = sccharacters_clean_text($_POST['character_description'] ?? ''); $notes = sccharacters_clean_text($_POST['character_notes'] ?? ''); $share_enabled = isset($_POST['character_share_enabled']) ? 1 : 0; + $is_pinned = isset($_POST['character_is_pinned']) ? 1 : 0; $posted_category_order_state = sccharacters_clean_text($_POST['category_order_state'] ?? ''); $posted_item_order_state_raw = trim((string) ($_POST['item_order_state'] ?? '')); @@ -815,7 +816,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { cl_sccharacter_description, cl_sccharacter_notes, cl_sccharacter_share_token, - cl_sccharacter_share_enabled + cl_sccharacter_share_enabled, + cl_sccharacter_is_pinned ) VALUES ( :owner_auth_id, :name, @@ -825,7 +827,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { :description, :notes, :share_token, - :share_enabled + :share_enabled, + :is_pinned )' ); $stmt->execute([ @@ -838,6 +841,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'notes' => $notes !== '' ? $notes : null, 'share_token' => sccharacters_generate_share_token($db), 'share_enabled' => $share_enabled, + 'is_pinned' => $is_pinned, ]); $new_character_id = (int) $db->lastInsertId(); @@ -863,6 +867,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $description = sccharacters_clean_text($_POST['character_description'] ?? ''); $notes = sccharacters_clean_text($_POST['character_notes'] ?? ''); $share_enabled = isset($_POST['character_share_enabled']) ? 1 : 0; + $is_pinned = isset($_POST['character_is_pinned']) ? 1 : 0; $posted_category_order_state = sccharacters_clean_text($_POST['category_order_state'] ?? ''); $posted_item_order_state_raw = trim((string) ($_POST['item_order_state'] ?? '')); @@ -886,7 +891,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { cl_sccharacter_avatar_url = :avatar_url, cl_sccharacter_description = :description, cl_sccharacter_notes = :notes, - cl_sccharacter_share_enabled = :share_enabled + cl_sccharacter_share_enabled = :share_enabled, + cl_sccharacter_is_pinned = :is_pinned WHERE cl_sccharacter_id = :id AND cl_sccharacter_owner_auth_id = :owner_auth_id' ); @@ -898,6 +904,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { 'description' => $description !== '' ? $description : null, 'notes' => $notes !== '' ? $notes : null, 'share_enabled' => $share_enabled, + 'is_pinned' => $is_pinned, 'id' => $character_id, 'owner_auth_id' => $current_owner_auth_id, ]); @@ -1177,7 +1184,7 @@ $stmt_characters = $db->prepare( LEFT JOIN tbl_sccharacteritems ci ON ci.cl_sccharacteritem_character_id = c.cl_sccharacter_id WHERE c.cl_sccharacter_owner_auth_id = :owner_auth_id GROUP BY c.cl_sccharacter_id - ORDER BY c.cl_sccharacter_updated_at DESC, c.cl_sccharacter_name ASC' + ORDER BY c.cl_sccharacter_is_pinned DESC, c.cl_sccharacter_updated_at DESC, c.cl_sccharacter_name ASC' ); $stmt_characters->execute(['owner_auth_id' => $current_owner_auth_id]); $characters = $stmt_characters->fetchAll(); @@ -1439,6 +1446,7 @@ $create_character = [ 'cl_sccharacter_description' => '', 'cl_sccharacter_notes' => '', 'cl_sccharacter_share_enabled' => 0, + 'cl_sccharacter_is_pinned' => 0, ]; $item_has_previous_page = $item_page > 1; $item_has_next_page = $item_page < $item_total_pages; @@ -1823,11 +1831,49 @@ if ($selected_character) { margin: 0; } + .character-card-title, + .hero-name-row { + display: flex; + align-items: center; + gap: 0.5rem; + min-width: 0; + } + .character-card-body h3 { font-size: 0.98rem; line-height: 1.25; } + .pin-indicator { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.8rem; + height: 1.8rem; + border-radius: 999px; + border: 1px solid rgba(162, 155, 120, 0.34); + background: rgba(162, 155, 120, 0.14); + color: #f8f3e1; + font-size: 0.95rem; + line-height: 1; + flex: 0 0 auto; + } + + .pin-indicator-input { + width: 2rem; + height: 2rem; + border-radius: 999px; + border: 1px solid rgba(162, 155, 120, 0.25); + background: rgba(162, 155, 120, 0.1); + color: #f8f3e1; + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1rem; + line-height: 1; + flex: 0 0 auto; + } + .muted { color: var(--text-soft); font-size: 0.88rem; @@ -2419,6 +2465,7 @@ if ($selected_character) {
+