mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-06 05:07:36 -05:00
Remove beans
This commit is contained in:
parent
81f571b226
commit
d8a5cdbf6a
|
|
@ -1,6 +0,0 @@
|
|||
beans:
|
||||
path: .beans
|
||||
prefix: sendou.ink-
|
||||
id_length: 4
|
||||
default_status: todo
|
||||
default_type: task
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
BIN
.beans/image.png
BIN
.beans/image.png
Binary file not shown.
|
Before Width: | Height: | Size: 68 KiB |
|
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0izp
|
||||
title: Rename CommandPalette to GlobalSearch
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T13:51:15Z
|
||||
updated_at: 2026-01-11T13:51:15Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The CommandPalette component is used more as a global search feature than a command palette. Rename it to better reflect its purpose.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Rename `CommandPalette.tsx` to `GlobalSearch.tsx`
|
||||
- [ ] Rename `CommandPalette.module.css` to `GlobalSearch.module.css`
|
||||
- [ ] Update all CSS class names from `commandPalette` to `globalSearch`
|
||||
- [ ] Update all imports and references across the codebase
|
||||
- [ ] Run checks to ensure nothing is broken
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0n0n
|
||||
title: Search category icons not shown on mobile
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T13:53:16Z
|
||||
updated_at: 2026-01-11T18:43:48Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
On narrow screens, the search/command palette category tabs (Users, Teams, Organizations, Tournaments) only show text labels without their icons. Icons should be visible on mobile to maintain visual consistency and improve scannability.
|
||||
|
||||
## Details
|
||||
|
||||
- The tabs currently show text-only on narrow screens
|
||||
- Icons help users quickly identify categories
|
||||
- Should match desktop behavior where icons are shown alongside text
|
||||
|
||||
## Fix
|
||||
|
||||
Added CSS in `CommandPalette.module.css`:
|
||||
|
||||
1. Added `flex-shrink: 0` to `picture` and `img` elements inside `.searchTypeRadio` to prevent icons from being compressed/hidden on narrow screens
|
||||
2. Added `flex-wrap: wrap` to `.searchTypeRadioGroup` to allow tabs to wrap to a new line on very narrow screens instead of overflowing
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0n4h
|
||||
title: Add any tournament to My Events
|
||||
status: draft
|
||||
type: feature
|
||||
created_at: 2026-01-11T12:55:45Z
|
||||
updated_at: 2026-01-11T12:55:45Z
|
||||
parent: sendou.ink-u4ag
|
||||
---
|
||||
|
||||
Allow users to add any tournament to their My Events page, not just tournaments they are organizing or have joined as a participant. This enables spectators to keep track of tournaments they want to follow or watch.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0q9m
|
||||
title: My Events page and components
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T11:45:35Z
|
||||
updated_at: 2026-01-11T12:50:56Z
|
||||
parent: sendou.ink-om3i
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Build the `/my-events` page with list view and event card components.
|
||||
|
||||
## Details
|
||||
|
||||
**Page requirements:**
|
||||
- Route: `/my-events`
|
||||
- Login required (redirect if not authenticated)
|
||||
- List view grouped by day (chronological)
|
||||
- Empty state with links to /calendar and /scrims
|
||||
|
||||
**Event card info:**
|
||||
- Name (tournament name or scrim opponent)
|
||||
- Time
|
||||
- Status
|
||||
- Check-in window (for tournaments)
|
||||
- Click navigates directly to tournament/scrim page
|
||||
|
||||
**Component sharing:**
|
||||
- Build components that can be reused by sidebar Events section
|
||||
- Handle both tournament and scrim event types
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add route to routes.ts
|
||||
- [ ] Create page component with loader
|
||||
- [ ] Create event list component (grouped by day)
|
||||
- [ ] Create event card component (handles tournament + scrim)
|
||||
- [ ] Implement empty state with links
|
||||
- [ ] Add translations
|
||||
- [ ] Style with CSS modules
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0sk2
|
||||
title: Remove trusted users management UI from settings
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-13T11:25:10Z
|
||||
updated_at: 2026-01-13T11:25:15Z
|
||||
parent: sendou.ink-255r
|
||||
blocking:
|
||||
- sendou.ink-kluy
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Delete the "Trusted Users" section from SendouQ settings page. This UI is replaced by the /friends page.
|
||||
|
||||
## Files to Modify
|
||||
|
||||
### app/features/sendouq-settings/routes/q.settings.tsx
|
||||
- Remove `<TrustedUsers />` component usage (line ~86)
|
||||
- Delete `TrustedUsers` function component (lines ~611-680)
|
||||
|
||||
### app/features/sendouq-settings/actions/q.settings.server.ts
|
||||
- Remove `REMOVE_TRUST` case from switch (lines ~44-49)
|
||||
|
||||
### app/features/sendouq-settings/q-settings-schemas.server.ts
|
||||
- Remove `REMOVE_TRUST` schema from union (lines ~68-71)
|
||||
|
||||
### app/features/sendouq-settings/loaders/q.settings.server.ts
|
||||
- Remove `trusted` from loader data
|
||||
|
||||
### app/features/sendouq-settings/QSettingsRepository.server.ts
|
||||
- Remove `findTrustedUsersByGiverId` function
|
||||
- Remove `deleteTrustedUser` function
|
||||
- (Keep other functions until full trust deprecation)
|
||||
|
||||
## i18n Keys to Remove
|
||||
|
||||
From `q` namespace:
|
||||
- `q:settings.trusted.header`
|
||||
- `q:settings.trusted.confirm`
|
||||
- `q:settings.trusted.trustedExplanation`
|
||||
- `q:settings.trusted.noTrustedExplanation`
|
||||
- `q:settings.trusted.teamExplanation`
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Remove TrustedUsers component from q.settings.tsx
|
||||
- [ ] Remove REMOVE_TRUST action handler
|
||||
- [ ] Remove REMOVE_TRUST schema
|
||||
- [ ] Remove trusted from loader
|
||||
- [ ] Remove repository functions (findTrustedUsersByGiverId, deleteTrustedUser)
|
||||
- [ ] Remove i18n keys
|
||||
- [ ] Run `npm run i18n:sync`
|
||||
- [ ] Verify settings page still works
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0uyd
|
||||
title: Database schema for friends system
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-13T09:31:56Z
|
||||
updated_at: 2026-01-14T19:14:51Z
|
||||
parent: sendou.ink-255r
|
||||
blocking:
|
||||
- sendou.ink-iulp
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Create database migrations for the friends system tables.
|
||||
|
||||
## Tables to Create
|
||||
|
||||
### Friendship
|
||||
```sql
|
||||
CREATE TABLE Friendship (
|
||||
id INTEGER PRIMARY KEY,
|
||||
userOneId INTEGER NOT NULL REFERENCES User(id),
|
||||
userTwoId INTEGER NOT NULL REFERENCES User(id),
|
||||
createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
UNIQUE(userOneId, userTwoId)
|
||||
);
|
||||
CREATE INDEX idx_friendship_user_one ON Friendship(userOneId);
|
||||
CREATE INDEX idx_friendship_user_two ON Friendship(userTwoId);
|
||||
```
|
||||
Invariant: userOneId < userTwoId to prevent duplicate relationships.
|
||||
|
||||
### FriendRequest
|
||||
```sql
|
||||
CREATE TABLE FriendRequest (
|
||||
id INTEGER PRIMARY KEY,
|
||||
senderId INTEGER NOT NULL REFERENCES User(id),
|
||||
receiverId INTEGER NOT NULL REFERENCES User(id),
|
||||
createdAt INTEGER NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
UNIQUE(senderId, receiverId)
|
||||
);
|
||||
CREATE INDEX idx_friend_request_receiver ON FriendRequest(receiverId);
|
||||
```
|
||||
|
||||
### SendouQ group changes
|
||||
|
||||
We also need to add support for invites in SQ without the user being in the queue. TBD what the table design looks like
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Create migration file
|
||||
- [x] Add tables to `app/db/tables.ts`
|
||||
- [x] Run migration and verify schema
|
||||
- [x] Add to test database
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
---
|
||||
# sendou.ink-0ze4
|
||||
title: Weapons pages
|
||||
status: draft
|
||||
type: epic
|
||||
created_at: 2026-01-11T12:10:47Z
|
||||
updated_at: 2026-01-11T12:10:47Z
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Individual weapon pages (`/weapons/<weapon-slug>`) with comprehensive weapon data, stats, and links to related content.
|
||||
|
||||
## Data Source
|
||||
|
||||
Parse weapon parameters from https://github.com/Leanny/splat3 into a format easy to use within sendou.ink.
|
||||
|
||||
## Features
|
||||
|
||||
### Parameter Comparison Table
|
||||
|
||||
- **Rows** = parameters (raw keys from Leanny's data, supports translation that can be filled out over time)
|
||||
- **Columns** = weapons in same category (e.g., Jr page shows all shooters)
|
||||
- **Current weapon pinned** in the table for easy comparison
|
||||
- **Patch history inline**: each cell shows current value + indicator if changed, expandable to see full history (which patch + date)
|
||||
|
||||
### Leaderboard & Popularity Stats
|
||||
|
||||
- **Top XP holder** for the weapon (name + XP) with link to full leaderboard
|
||||
- **Popularity** (top 500 appearances) - shown both:
|
||||
- Overall across all weapons
|
||||
- Within the weapon's category
|
||||
- Data already exists in sendou.ink database
|
||||
|
||||
### Rich Previews (5 items each)
|
||||
|
||||
- **5 recent vods** of the weapon
|
||||
- **5 popular builds** for the weapon
|
||||
- **5 art pieces** tagged by the weapon
|
||||
|
||||
### Simple Links
|
||||
|
||||
- Free agents using this weapon
|
||||
- Build analyzer link
|
||||
- Object damage calculator link
|
||||
|
||||
## Navigation
|
||||
|
||||
- No landing page at `/weapons`
|
||||
- No category pages
|
||||
- Users access individual weapon pages directly via menu (weapon mega menu)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Individual weapon pages already exist as placeholders (e.g., `/weapons/splattershot-jr`)
|
||||
- Leaderboard and popularity data already available in database
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
# sendou.ink-10ai
|
||||
title: Implement prestige calculation
|
||||
status: todo
|
||||
type: feature
|
||||
created_at: 2026-01-12T09:21:18Z
|
||||
updated_at: 2026-01-12T09:21:18Z
|
||||
parent: sendou.ink-ylq5
|
||||
---
|
||||
|
||||
Implement the tournament prestige calculation based on research findings.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Calculate prestige from registered teams' seeding power
|
||||
- Available at registration time (not just after results)
|
||||
- Works for both upcoming and historical tournaments
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Create function in /app/features/tournament/ or /app/features/mmr/
|
||||
- Query top N teams' avgSeedingSkillOrdinal
|
||||
- Apply formula from design task
|
||||
- Return prestige score/tier
|
||||
|
||||
## Usage
|
||||
|
||||
- Called by stream aggregation service for ranking
|
||||
- May be displayed on tournament pages (future)
|
||||
- May be stored for historical tracking (future)
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Prestige formula design (sendou.ink-XXX)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
# sendou.ink-18y6
|
||||
title: Inconsistent notification dot colors
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T19:22:01Z
|
||||
updated_at: 2026-01-12T16:04:11Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The notification dot color is inconsistent between:
|
||||
- The notification bell / user menu tab indicator
|
||||
- The dots shown in the actual notification popover
|
||||
|
||||
These should use consistent styling.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
# sendou.ink-1kb8
|
||||
title: Show times on mobile Events panel
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
tags:
|
||||
- my-events-epic
|
||||
created_at: 2026-01-11T09:48:18Z
|
||||
updated_at: 2026-01-11T13:24:31Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The mobile Events panel currently only shows tournament names without any time information. Add day headers and event times to help players know when things are happening.
|
||||
|
||||
## Current state
|
||||
|
||||
Panel shows a flat list of tournaments with just:
|
||||
- Tournament logo
|
||||
- Tournament name
|
||||
|
||||
## Proposed design
|
||||
|
||||
Group events by day with headers, then show time per event:
|
||||
|
||||
```
|
||||
Today
|
||||
3:00 PM PICNIC #2
|
||||
7:00 PM In The Zone 22
|
||||
|
||||
Tomorrow
|
||||
2:00 PM Paddling Pool 253
|
||||
5:00 PM Swim or Sink 101
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Add day header groupings (Today, Tomorrow, weekday names, or dates)
|
||||
- [x] Show event start time next to each entry
|
||||
- [x] Ensure times display in user's local timezone
|
||||
- [x] Test with events spanning multiple days
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
# sendou.ink-1l22
|
||||
title: CSS rework for modern practices and theming accessibility
|
||||
status: in-progress
|
||||
type: epic
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:33:26Z
|
||||
updated_at: 2026-01-11T09:34:23Z
|
||||
---
|
||||
|
||||
## Why
|
||||
|
||||
The existing CSS architecture needed modernization to support:
|
||||
|
||||
1. **Consistency** - Standardized design tokens and variable naming conventions
|
||||
2. **Modern CSS practices** - Leveraging newer CSS features for better maintainability
|
||||
3. **Accessibility for user-defined themes** - Making it easy for users to customize themes while maintaining readability and contrast requirements
|
||||
|
||||
## What's been done
|
||||
|
||||
- Redefined all styles in `vars.css` with a consistent naming convention
|
||||
- Established design tokens for colors, spacing, typography, and other properties
|
||||
- Created a foundation that supports user theme customization while preserving accessibility
|
||||
|
||||
## Goals
|
||||
|
||||
- All components use CSS variables from `vars.css` consistently
|
||||
- Theme customization is straightforward and accessible
|
||||
- Color contrast and other accessibility requirements are maintained across all themes
|
||||
- Reduced CSS specificity conflicts and improved maintainability
|
||||
|
||||
## Completion criteria
|
||||
|
||||
All child tickets resolved and the new CSS variable system is fully adopted across the codebase.
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
# sendou.ink-1qfh
|
||||
title: Fix notification button and indicator dot overlay
|
||||
status: scrapped
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:37:03Z
|
||||
updated_at: 2026-01-11T12:53:25Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
The notification bell icon and the unread indicator dot are displayed side by side instead of the dot being overlayed on top of the bell icon.
|
||||
|
||||
## Screenshot
|
||||
|
||||
The blue notification dot appears next to the bell icon rather than positioned as an overlay badge on the icon.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The notification indicator dot should be positioned as an overlay on the bell icon (typically top-right corner), following standard notification badge UI patterns.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Notification dot is positioned as an overlay on the bell icon
|
||||
- Dot placement follows common UI conventions (e.g., top-right corner)
|
||||
- Works correctly on both desktop sidebar and mobile layouts
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
---
|
||||
# sendou.ink-24f6
|
||||
title: Analyze tournament seeding data distribution
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:21:17Z
|
||||
updated_at: 2026-01-12T09:21:23Z
|
||||
parent: sendou.ink-ylq5
|
||||
blocking:
|
||||
- sendou.ink-h9ht
|
||||
---
|
||||
|
||||
Research task: Analyze existing tournament data to understand seeding skill distributions.
|
||||
|
||||
## Goals
|
||||
|
||||
- Understand the range and distribution of avgSeedingSkillOrdinal values
|
||||
- Identify what distinguishes 'stacked' tournaments from casual ones
|
||||
- Find natural breakpoints for prestige tiers
|
||||
- Compare team counts vs skill levels
|
||||
|
||||
## Data to Analyze
|
||||
|
||||
- All finalized tournaments (RANKED and UNRANKED)
|
||||
- Top 8 teams' average seeding skill ordinal
|
||||
- Distribution across different tournament sizes
|
||||
|
||||
## Output
|
||||
|
||||
- Report with findings
|
||||
- Recommendations for baseline comparison value
|
||||
- Suggested tier boundaries (if discrete tiers make sense)
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Can use db-prod.sqlite3 for real data
|
||||
- Write analysis script or SQL queries
|
||||
- Consider visualizing distributions
|
||||
|
|
@ -1,128 +0,0 @@
|
|||
---
|
||||
# sendou.ink-255r
|
||||
title: Friends feature
|
||||
status: todo
|
||||
type: epic
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:27:40Z
|
||||
updated_at: 2026-01-13T09:31:29Z
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Friends functionality for sendou.ink, replacing the current "Trusted" system. Enables users to see their friends in one place and quickly find what they're looking for (SendouQ group, tournament).
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Relationship Model
|
||||
- **Mutual friendship**: User A sends request → User B accepts → both are friends
|
||||
- **Friends = Trusted**: Friendship automatically grants all current trust permissions (quick-add to groups, scrim pickups)
|
||||
- **Soft limit**: ~200 friends maximum per user
|
||||
|
||||
### Display Priority Hierarchy
|
||||
The sidebar and /friends page show users from multiple relationship sources, prioritized as:
|
||||
|
||||
1. **Explicit friends** (highest priority) - Users you've mutually friended
|
||||
2. **Team members** - Members of teams you belong to
|
||||
3. **Shared association members** (lowest priority) - Members of organizations/associations you share, including Plus server members
|
||||
|
||||
Within each tier, users with activity (SendouQ/tournaments) are shown first.
|
||||
|
||||
### Activity Visibility
|
||||
- SendouQ group status (group count like "2/4")
|
||||
- Tournament registration/participation
|
||||
- No online/last seen tracking - just activities
|
||||
- All connections see your activity (no privacy controls for MVP)
|
||||
|
||||
### Permission Model
|
||||
- **Trusted permissions** (quick-add to groups without invite): Friends only
|
||||
- **Quick invite** (send invite notification): All connections (friends, teammates, associations)
|
||||
- Teammates and association members receive invite and must accept
|
||||
|
||||
### Migration from Trust System
|
||||
- If A trusts B AND B trusts A → auto-create friendship
|
||||
- One-way trust relationships → deleted
|
||||
- TrustRelationship table eventually deprecated
|
||||
|
||||
## Features
|
||||
|
||||
### Friend Requests
|
||||
- Send from: user profile page, invite link join flow (checkbox like current trust)
|
||||
- Notifications: in-app only (notification bell/dropdown)
|
||||
- States: pending outgoing, pending incoming, accepted, declined
|
||||
|
||||
### Sidebar Display
|
||||
- Mixed list (no grouping by relationship type)
|
||||
- Quota system: X slots for SendouQ activity, Y slots for tournament activity
|
||||
- Priority: explicit friends → team members → association members
|
||||
- Within each tier: active first, then most recent interaction
|
||||
- Each entry shows: avatar, name, activity subtitle, badge
|
||||
- "See all" link to /friends page
|
||||
|
||||
### /friends Page
|
||||
- **Grouped sections** with headers (unlike sidebar)
|
||||
- **Pending requests section**: incoming and outgoing requests
|
||||
- **Friends section**: explicit friends with activity status
|
||||
- **Teammates section**: team members (with team name context)
|
||||
- **Connections section**: association/Plus members
|
||||
- **Management**: unfriend, search/filter across all sections
|
||||
- **Mutual friends**: show mutual friends count/list on profiles
|
||||
|
||||
### Quick Invite to SendouQ
|
||||
- "Invite friend" button in SendouQ group lobby
|
||||
- Can invite any connection (friends, teammates, associations)
|
||||
- Sends notification to selected user(s)
|
||||
- User can accept to join group directly
|
||||
- Only friends can be directly added (trusted); others must accept invite
|
||||
|
||||
### Mutual Friends Display
|
||||
- Show on user profiles
|
||||
- Count of mutual friends
|
||||
- Preview of mutual friend avatars/names
|
||||
|
||||
## Database Schema
|
||||
|
||||
### New Tables
|
||||
|
||||
```sql
|
||||
-- Friendship (mutual relationship)
|
||||
CREATE TABLE Friendship (
|
||||
// ...
|
||||
);
|
||||
-- Invariant: userOneId < userTwoId to prevent duplicates
|
||||
|
||||
-- Friend Request
|
||||
CREATE TABLE FriendRequest (
|
||||
// ...
|
||||
);
|
||||
|
||||
### Existing Tables Used
|
||||
- `TeamMember` - for teammate relationships
|
||||
- `AssociationMember` - for association members
|
||||
- `PlusTier` - for Plus server membership
|
||||
|
||||
## Future Enhancements (out of scope)
|
||||
|
||||
- Private messaging between friends
|
||||
- Friend activity feed (tournament placements, rank changes)
|
||||
- Friend categories/groups
|
||||
- Block list
|
||||
- LFG status visible to friends
|
||||
- Email notifications for friend requests
|
||||
- Privacy controls per connection type
|
||||
- Tournament team forming (see sendou.ink-5x6m)
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
- [ ] Database schema and migrations created
|
||||
- [ ] FriendRepository with all CRUD operations
|
||||
- [ ] Friend request flow (send, accept, decline, cancel)
|
||||
- [ ] Sidebar shows real friends/teammates/connections with activity
|
||||
- [ ] /friends page with grouped sections and management
|
||||
- [ ] Profile page friend button and mutual friends
|
||||
- [ ] Quick invite to SendouQ group (all connections)
|
||||
- [ ] Group invite accept/decline flow for non-friends
|
||||
- [ ] Migration script for trust → friendship
|
||||
- [ ] Update all trust-dependent features to use friendship
|
||||
- [ ] Remove/deprecate TrustRelationship table
|
||||
- [ ] Tests for friend operations
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
# sendou.ink-2oby
|
||||
title: Fix handleRadioGroupKeyDown in CommandPalette
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:55Z
|
||||
updated_at: 2026-01-13T18:49:27Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The handleRadioGroupKeyDown function is not working. Location: app/components/layout/CommandPalette.tsx:151
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
# sendou.ink-368p
|
||||
title: Measure and optimize weapon params JSON performance
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T15:23:48Z
|
||||
updated_at: 2026-01-13T15:23:48Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
The weapon params are loaded from a large JSON file and calculated at request time. Tasks:
|
||||
|
||||
## Checklist
|
||||
- [ ] Measure the current performance penalty of loading/parsing the big JSON at request time
|
||||
- [ ] Investigate if caching or pre-computation could improve performance
|
||||
- [ ] Implement optimizations if the perf impact is significant
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-36dp
|
||||
title: Check if pagination styles can be improved
|
||||
status: completed
|
||||
type: task
|
||||
created_at: 2026-01-11T12:35:22Z
|
||||
updated_at: 2026-01-11T12:35:22Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
Review the current pagination component styling and identify potential improvements that align with the CSS rework goals (modern practices, theming, accessibility).
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
# sendou.ink-36pm
|
||||
title: Add weapon mega menu to mobile design
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:31:09Z
|
||||
updated_at: 2026-01-11T18:58:39Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
The desktop layout has a weapon mega menu in the top navigation bar that allows users to quickly access weapon-specific pages. This menu is missing from the mobile design, which uses bottom tab navigation instead.
|
||||
|
||||
## Context
|
||||
|
||||
Mobile users currently lack quick access to weapon-related content that desktop users have via the top menu bar category dropdowns.
|
||||
|
||||
## Possible approaches
|
||||
|
||||
- Add weapon navigation to the mobile menu modal
|
||||
- Create a dedicated weapons section accessible from mobile tabs
|
||||
- Integrate weapon categories into the existing mobile menu structure
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Mobile users can access the same weapon navigation options as desktop users
|
||||
- Navigation is intuitive and follows the established mobile design patterns
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
# sendou.ink-3hgl
|
||||
title: Fix black background on date/time inputs in Chrome
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-11T12:36:28Z
|
||||
updated_at: 2026-01-11T12:36:28Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
Some native input types (time, datetime-local, week, month) display with black backgrounds or styling issues in Chrome. Need to investigate the root cause and apply a consistent fix across all affected input types.
|
||||
|
||||
## Details
|
||||
- Affected inputs: time, datetime-local, week, month (and possibly others)
|
||||
- Browser: Chrome
|
||||
- The icons and placeholder text appear correctly but there seems to be a color scheme conflict
|
||||
|
||||
## Checklist
|
||||
- [ ] Identify which CSS rules cause the black background
|
||||
- [ ] Check if it's related to color-scheme property or browser defaults
|
||||
- [ ] Apply a fix that works for all affected input types at once
|
||||
- [ ] Test in Chrome and other browsers
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
---
|
||||
# sendou.ink-3k3u
|
||||
title: Friend request API routes
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-13T09:32:19Z
|
||||
updated_at: 2026-01-13T10:18:25Z
|
||||
parent: sendou.ink-255r
|
||||
blocking:
|
||||
- sendou.ink-f1rm
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Implement action handlers for friend request operations following the codebase's action pattern.
|
||||
|
||||
## File
|
||||
|
||||
`app/features/friends/actions/friends.ts` (same route as /friends page)
|
||||
|
||||
## Action Pattern
|
||||
|
||||
Uses `_action` field in form submissions with switch case:
|
||||
|
||||
```typescript
|
||||
export const action: ActionFunction = async ({ request }) => {
|
||||
const user = await requireUser(request);
|
||||
const data = await parseRequestPayload({ request });
|
||||
|
||||
switch (data._action) {
|
||||
case "SEND_REQUEST": {
|
||||
// Send friend request
|
||||
// Validate: not already friends, no pending request, under limit
|
||||
// Create FriendRequest record
|
||||
// Create notification for receiver
|
||||
return json({ success: true });
|
||||
}
|
||||
case "ACCEPT_REQUEST": {
|
||||
// Accept incoming friend request
|
||||
// Validate: request exists, user is receiver
|
||||
// Delete FriendRequest, create Friendship
|
||||
// Create notification for sender
|
||||
return json({ success: true });
|
||||
}
|
||||
case "DECLINE_REQUEST": {
|
||||
// Decline incoming friend request
|
||||
// Validate: request exists, user is receiver
|
||||
// Delete FriendRequest
|
||||
return json({ success: true });
|
||||
}
|
||||
case "CANCEL_REQUEST": {
|
||||
// Cancel outgoing friend request
|
||||
// Validate: request exists, user is sender
|
||||
// Delete FriendRequest
|
||||
return json({ success: true });
|
||||
}
|
||||
case "UNFRIEND": {
|
||||
// Remove friendship
|
||||
// Validate: friendship exists
|
||||
// Delete Friendship record
|
||||
return json({ success: true });
|
||||
}
|
||||
default:
|
||||
throw new Response("Invalid action", { status: 400 });
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Form Data
|
||||
|
||||
```typescript
|
||||
// SEND_REQUEST
|
||||
{ _action: "SEND_REQUEST", targetUserId: number }
|
||||
|
||||
// ACCEPT_REQUEST
|
||||
{ _action: "ACCEPT_REQUEST", requestId: number }
|
||||
// or
|
||||
{ _action: "ACCEPT_REQUEST", senderId: number }
|
||||
|
||||
// DECLINE_REQUEST
|
||||
{ _action: "DECLINE_REQUEST", requestId: number }
|
||||
|
||||
// CANCEL_REQUEST
|
||||
{ _action: "CANCEL_REQUEST", requestId: number }
|
||||
|
||||
// UNFRIEND
|
||||
{ _action: "UNFRIEND", friendId: number }
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
- `SEND_REQUEST`:
|
||||
- Target user exists
|
||||
- Not already friends
|
||||
- No pending request in either direction
|
||||
- Sender under friend limit (~200)
|
||||
|
||||
- `ACCEPT_REQUEST`:
|
||||
- Request exists
|
||||
- Current user is the receiver
|
||||
- Both users under friend limit
|
||||
|
||||
- `UNFRIEND`:
|
||||
- Friendship exists
|
||||
- Current user is part of the friendship
|
||||
|
||||
## Notifications
|
||||
|
||||
- `SEND_REQUEST` → notify receiver "X sent you a friend request"
|
||||
- `ACCEPT_REQUEST` → notify original sender "X accepted your friend request"
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add action handler to friends.tsx
|
||||
- [ ] SEND_REQUEST action with validation
|
||||
- [ ] ACCEPT_REQUEST action
|
||||
- [ ] DECLINE_REQUEST action
|
||||
- [ ] CANCEL_REQUEST action
|
||||
- [ ] UNFRIEND action
|
||||
- [ ] Integration with notification system
|
||||
- [ ] Error handling and user feedback
|
||||
- [ ] Tests for each action
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
---
|
||||
# sendou.ink-3qrp
|
||||
title: Improve mobile menu grid alignment and prevent label wrapping
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:42:29Z
|
||||
updated_at: 2026-01-11T18:31:05Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
On mobile, the menu grid has alignment issues and some page labels are breaking into two or three lines, creating an inconsistent and cluttered appearance.
|
||||
|
||||
## Screenshot
|
||||
|
||||
Labels breaking to multiple lines:
|
||||
- "Build Analyzer" (2 lines)
|
||||
- "User Search" (2 lines)
|
||||
- "Top Search" (2 lines)
|
||||
- "Tier List Maker" (3 lines)
|
||||
- "Plus Server" (2 lines)
|
||||
- "Leaderboards" wrapping
|
||||
|
||||
Meanwhile other labels like "Settings", "SendouQ", "Builds", "Scrims", "LFG" etc. fit on one line.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
- Menu items should be consistently aligned
|
||||
- Labels should ideally fit on a single line
|
||||
- If wrapping is unavoidable, it should be limited to two lines maximum
|
||||
|
||||
## Possible solutions
|
||||
|
||||
- Reduce number of columns to give more horizontal space per item
|
||||
- Use shorter label names where possible
|
||||
- Adjust font size for labels
|
||||
- Use text truncation with ellipsis for long labels
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Menu grid is visually balanced and aligned
|
||||
- No labels break to three lines
|
||||
- Minimize two-line labels where possible
|
||||
- Consistent spacing between menu items
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
# sendou.ink-4m0t
|
||||
title: Add STREAM_CURATOR role to permissions
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:20:30Z
|
||||
updated_at: 2026-01-12T09:21:32Z
|
||||
parent: sendou.ink-r6ry
|
||||
blocking:
|
||||
- sendou.ink-x535
|
||||
---
|
||||
|
||||
Add new STREAM_CURATOR permission role to allow users to add stream links to calendar events.
|
||||
|
||||
## Requirements
|
||||
|
||||
- New role in existing permissions system
|
||||
- Granted by staff (same flow as 'is artist' role)
|
||||
- Allows adding stream link(s) to calendar events user created
|
||||
- Scoped to own events only
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create migration to add `isStreamCurator` column to User table (Boolean, default 0)
|
||||
- [ ] Add `"STREAM_CURATOR"` to Role type in `/app/modules/permissions/types.ts`
|
||||
- [ ] Add mapping in `/app/modules/permissions/mapper.server.ts` userRoles function: `if (user.isStreamCurator) roles.push("STREAM_CURATOR")`
|
||||
- [ ] Add `makeStreamCuratorByUserId(userId)` function in `/app/features/admin/AdminRepository.server.ts`
|
||||
- [ ] Add `"STREAM_CURATOR"` action case in `/app/features/admin/actions/admin.server.ts`
|
||||
- [ ] Add `GiveStreamCurator` component in `/app/features/admin/routes/admin.tsx` (visible to staff)
|
||||
|
||||
## Implementation Pattern
|
||||
|
||||
Follow existing pattern from `isArtist`:
|
||||
|
||||
```typescript
|
||||
// AdminRepository.server.ts
|
||||
export function makeStreamCuratorByUserId(userId: number) {
|
||||
return db
|
||||
.updateTable("User")
|
||||
.set({ isStreamCurator: 1 })
|
||||
.where("User.id", "=", userId)
|
||||
.execute();
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// admin.tsx - add to AdminActions, visible to isStaff
|
||||
{isStaff ? <GiveStreamCurator /> : null}
|
||||
```
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
# sendou.ink-5d8q
|
||||
title: Show notification dot on mobile You tab
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T13:06:55Z
|
||||
updated_at: 2026-01-11T19:13:22Z
|
||||
parent: 6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
The desktop sidebar shows a notification indicator dot when there are unseen notifications, but the mobile "You" tab in the bottom navigation does not have this indicator.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The mobile "You" tab should display a notification dot when there are unseen notifications, matching the desktop behavior.
|
||||
|
||||
## Location
|
||||
|
||||
- Mobile tab bar: `app/components/MobileNav.tsx` (MobileTabBar component)
|
||||
- Desktop notification indicator for reference: `app/components/layout/index.tsx`
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
# sendou.ink-5x6m
|
||||
title: Tournament team forming
|
||||
status: draft
|
||||
type: epic
|
||||
created_at: 2026-01-13T06:49:55Z
|
||||
updated_at: 2026-01-13T06:49:55Z
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Reuse the `SendouQ` class to allow for SendouQ-like UI to create tournaments teams.
|
||||
|
||||
## Context
|
||||
|
||||
- Depends on: Friends feature (sendou.ink-255r)
|
||||
|
||||
## Potential Features
|
||||
|
||||
- Can join the "queue" either solo or with a team
|
||||
- When registering solo, toggle whether they want to stay around as a sub if doesn't have time to form a team before reg closes
|
||||
|
||||
## Notes
|
||||
|
||||
This is a placeholder epic. Scope to be defined after Friends feature is complete.
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
# sendou.ink-5ysz
|
||||
title: Add weapon parameter translations to i18n
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:22:15Z
|
||||
updated_at: 2026-01-11T12:22:15Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Add weapon parameter keys to the existing i18n translation system so raw parameter names can be displayed in human-readable form.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Add new translation namespace or extend existing `weapons` namespace
|
||||
- Map raw Leanny parameter keys to readable names
|
||||
- Initially can be partial - untranslated keys display as-is
|
||||
- Support incremental addition of translations over time
|
||||
|
||||
## Example
|
||||
|
||||
```json
|
||||
{
|
||||
"params": {
|
||||
"DamageParam_ValueMax": "Max Damage",
|
||||
"DamageParam_ValueMin": "Min Damage",
|
||||
"MoveSpeed": "Movement Speed"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Run `npm run i18n:sync` after adding new English translations
|
||||
- Keys should match exactly what comes from Leanny's data
|
||||
- We should have a way to know in the table which keys have translation and which don't for conditional rendering
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
---
|
||||
# sendou.ink-6eko
|
||||
title: Desktop sidebar and mobile tabs layout
|
||||
status: in-progress
|
||||
type: epic
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:29Z
|
||||
updated_at: 2026-01-11T09:34:23Z
|
||||
blocking:
|
||||
- sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Why
|
||||
|
||||
The previous layout had several limitations holding back the player experience:
|
||||
|
||||
1. **Poor mobile UX** - Navigation wasn't optimized for mobile players
|
||||
2. **Hard to navigate** - No global search, sidebar only appeared on front page making it difficult to find features
|
||||
3. **Slow path to matches** - Competitive players had too many clicks to join matches or check their tournament status
|
||||
4. **No foundation for scheduling** - Future features like team scheduling and league match scheduling need a persistent navigation structure
|
||||
5. **Streams not visible** - Community streams weren't highlighted, missing opportunity to showcase active players
|
||||
|
||||
## Goals
|
||||
|
||||
- Make it easy for competitive players to get into matches fast (1-click access to active matches/tournaments)
|
||||
- Provide persistent navigation across all pages via sidebar (desktop) and bottom tabs (mobile)
|
||||
- Add global search via command palette to quickly find users, teams, organizations, and tournaments
|
||||
- Lay foundation for upcoming features: friend group quick-join, team scheduling, league scheduling
|
||||
- Better highlight community content like streams
|
||||
|
||||
## What's been built
|
||||
|
||||
- **Desktop**: Fixed sidebar with user profile, tournament calendar, friends list, streams + top menu bar with category dropdowns
|
||||
- **Mobile**: Bottom tab bar with modal panels for menu, friends, tournaments, and user profile
|
||||
- **Command palette**: Global search (Cmd/Ctrl+K) for users, teams, organizations, tournaments
|
||||
- **Breadcrumb navigation**: Context-aware page hierarchy
|
||||
- **Quick match access**: Tournament and SendouQ match status prominently displayed
|
||||
|
||||
## Completion criteria
|
||||
|
||||
All child tickets resolved.
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
# sendou.ink-6i41
|
||||
title: Move Settings to same row as user avatar in mobile user tab
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:40:48Z
|
||||
updated_at: 2026-01-11T13:11:56Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
On mobile, in the user tab modal, the Settings option is positioned at the bottom of the panel. It should instead be on the same row as the user avatar and name.
|
||||
|
||||
## Current behavior
|
||||
|
||||
- User avatar + name (Sendou) on one row
|
||||
- Notifications section
|
||||
- Settings at the bottom (separate location)
|
||||
|
||||
## Expected behavior
|
||||
|
||||
- User avatar + name + Settings on the same row
|
||||
- Notifications section below
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Settings button/link is positioned on the same row as the user avatar and name
|
||||
- Layout is balanced and visually clean
|
||||
- Settings remains easily accessible
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
# sendou.ink-7omz
|
||||
title: Try stage banner style for tournament matches
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T19:25:36Z
|
||||
updated_at: 2026-01-11T19:25:36Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Experiment with using "stage banner" style images for tournament match displays instead of the regular sized stage images. Stage banner images are available in Lean's splat3 assets repository and might provide a better visual appearance.
|
||||
|
||||
## Context
|
||||
|
||||
Currently, tournament matches use regular stage images (`stageImageUrl`) as background for the `FancyStageBanner` component (in `app/features/tournament-bracket/components/StartedMatch.tsx`). The banner dimensions are 10rem tall with `background-size: cover`.
|
||||
|
||||
Lean's repository may have wider/more panoramic stage banners that could better fit this banner-style layout without as much cropping.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Locate stage banner images from Lean's splat3 repository
|
||||
- [ ] Compare visual appearance with current stage images
|
||||
- [ ] If they look better, add banner images to static assets
|
||||
- [ ] Update `stageImageUrl` or create new `stageBannerUrl` utility
|
||||
- [ ] Update `FancyStageBanner` component to use banner images
|
||||
|
||||
## Files
|
||||
|
||||
- `app/features/tournament-bracket/components/StartedMatch.tsx:290-292` - stageNameToBannerImageUrl function
|
||||
- `app/features/tournament-bracket/tournament-bracket.module.css:57-71` - stageBanner styling
|
||||
- `app/utils/urls.ts:493-494` - stageImageUrl function
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
---
|
||||
# sendou.ink-8vei
|
||||
title: Create weapon stats summary component
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:22:34Z
|
||||
updated_at: 2026-01-11T12:22:34Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create a React component that displays weapon leaderboard and popularity statistics.
|
||||
|
||||
## Features
|
||||
|
||||
- **Top XP holder** - Player name + XP value, links to full leaderboard
|
||||
- **Popularity stats** - Top 500 appearances shown in two contexts:
|
||||
- Overall rank across all weapons
|
||||
- Rank within the weapon's category
|
||||
|
||||
## Data Sources
|
||||
|
||||
- XP data: `XPLeaderboard.server.ts` - `weaponXPLeaderboard(weaponId)`
|
||||
- Popularity: `XRankPlacement` table queries
|
||||
|
||||
## Props
|
||||
|
||||
- `topPlayer` - { name, xp, playerId }
|
||||
- `popularity` - { overallRank, categoryRank, appearances }
|
||||
- `weaponId` - for leaderboard link
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Use existing player link components if available
|
||||
- Leaderboard link goes to `/leaderboards?type=XP-WEAPON-{weaponId}`
|
||||
- Caching for performance?
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
---
|
||||
# sendou.ink-9cpl
|
||||
title: Create /streams page route and basic layout
|
||||
status: todo
|
||||
type: feature
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:19:55Z
|
||||
updated_at: 2026-01-12T12:07:16Z
|
||||
parent: sendou.ink-r6ry
|
||||
blocking:
|
||||
- sendou.ink-kph0
|
||||
- sendou.ink-u6b2
|
||||
- sendou.ink-ae15
|
||||
---
|
||||
|
||||
Create the new /streams page that will serve as the central hub for all community streams.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Add route at /streams
|
||||
- Two-section layout: Live streams and Upcoming streams
|
||||
- Desktop: Single column (can iterate on two-column later)
|
||||
- Mobile: Single column stacked layout
|
||||
- Support query params for filtering
|
||||
|
||||
## Query Params
|
||||
|
||||
- `?source=sendouq` - Filter to only SendouQ streams
|
||||
- `?source=tournament` - Filter to only tournament streams
|
||||
- `?tournament=:id` - Filter to specific tournament (for redirect from `/to/:id/streams`)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add route to `routes.ts`: `route("/streams", "features/streams/routes/streams.tsx")`
|
||||
- [ ] Create `/app/features/streams/routes/streams.tsx`
|
||||
- [ ] Create loader that calls aggregation service
|
||||
- [ ] Create stream card component
|
||||
- [ ] Implement "Live" section with live streams
|
||||
- [ ] Implement "Upcoming" section with upcoming calendar events
|
||||
- [ ] Add empty state for when no streams are live
|
||||
- [ ] Add filter tabs/dropdown for source filtering
|
||||
- [ ] Add i18n translations
|
||||
|
||||
## Stream Card Design
|
||||
|
||||
Each stream card should show:
|
||||
- Thumbnail/avatar image
|
||||
- Stream title or streamer name
|
||||
- Source indicator (SendouQ badge, Tournament name, Event name)
|
||||
- Subtitle (round name, match info, scheduled time)
|
||||
- LIVE badge or scheduled time
|
||||
- Click to expand Twitch embed (if Twitch)
|
||||
- External link for non-Twitch streams
|
||||
|
||||
## Empty State
|
||||
|
||||
When no streams are live:
|
||||
- Show friendly message: "No live streams right now"
|
||||
- Show upcoming streams section more prominently
|
||||
- Consider showing recent VODs (future enhancement)
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Create in `/app/features/streams/` folder
|
||||
- Loader calls aggregation service (sendou.ink-nw8b)
|
||||
- Twitch streams can embed inline (sendou.ink-r717)
|
||||
- Non-Twitch streams (YouTube, etc.) open in new tab
|
||||
|
||||
## Dependencies
|
||||
|
||||
- sendou.ink-nw8b: Stream aggregation service (for data)
|
||||
- sendou.ink-r717: Twitch embed component (for playback)
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
# sendou.ink-a9gl
|
||||
title: Add stream links field to CalendarEvent
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:20:30Z
|
||||
updated_at: 2026-01-12T09:21:32Z
|
||||
parent: sendou.ink-r6ry
|
||||
blocking:
|
||||
- sendou.ink-x535
|
||||
---
|
||||
|
||||
Add database table for storing stream links associated with calendar events.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Support multiple stream links per event (Twitch, YouTube, etc.)
|
||||
- Links are just URLs - platform-agnostic
|
||||
- Only STREAM_CURATOR users can add links to their own events
|
||||
|
||||
## Data Model
|
||||
|
||||
New join table `CalendarEventStream`:
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| id | number | Primary key |
|
||||
| calendarEventId | number | FK to CalendarEvent |
|
||||
| url | string | Full URL to stream (e.g., `https://twitch.tv/username`) |
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create migration `0XXX-calendar-event-stream.ts` with CalendarEventStream table
|
||||
- [ ] Add `CalendarEventStream` interface to `/app/db/tables.ts`
|
||||
- [ ] Add TypeScript types in calendar feature types file
|
||||
- [ ] Create repository functions: `addStreamToEvent`, `removeStreamFromEvent`, `getStreamsForEvent`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Keep it simple: just store the URL as-is
|
||||
- No validation against external APIs (just basic URL format check)
|
||||
- Display can extract platform from URL (twitch.tv, youtube.com, etc.) if needed for icon
|
||||
- First version only support Twitch and YouTube links/embeds, might be expanded later (so store the full stream URL to the DB)
|
||||
- Max links per event: consider a reasonable limit (e.g., 5)
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
---
|
||||
# sendou.ink-ae15
|
||||
title: Add /streams link to sidebar and mobile menu
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-12T09:20:56Z
|
||||
updated_at: 2026-01-12T09:20:56Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Add navigation link to the new /streams page.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Add link in sidebar streams section (below the top 3 streams)
|
||||
- Add to mobile menu in appropriate location
|
||||
- Link text: "All streams" (or localized equivalent)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add link in desktop sidebar after stream cards (`/app/components/layout/index.tsx`)
|
||||
- [ ] Add link in mobile menu streams section (`/app/components/MobileNav.tsx`)
|
||||
- [ ] Add i18n translation key: `common:nav.allStreams` = "All streams"
|
||||
- [ ] Run `npm run i18n:sync` after adding translation
|
||||
- [ ] Style link consistently with other section links
|
||||
|
||||
## Implementation
|
||||
|
||||
Desktop sidebar (in layout/index.tsx):
|
||||
```tsx
|
||||
<SideNavHeader icon={<TwitchIcon />}>Streams</SideNavHeader>
|
||||
{streams.map(stream => <SideNavLink ... />)}
|
||||
<Link to="/streams" className="...">All streams →</Link>
|
||||
```
|
||||
|
||||
Mobile menu (in MobileNav.tsx):
|
||||
```tsx
|
||||
// In MenuOverlay streams section
|
||||
{streams.map(stream => ...)}
|
||||
<Link to="/streams">All streams</Link>
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
inline link (the header becomes link) prompt user for resolution (TBD)
|
||||
|
||||
## Notes
|
||||
|
||||
- Should appear after the stream cards, not before
|
||||
- Use right arrow or chevron icon to indicate "see more"
|
||||
- Same pattern will be used for "Events" and "Friends" sections later
|
||||
|
||||
## Dependencies
|
||||
|
||||
- sendou.ink-9cpl: /streams page must exist first
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
# sendou.ink-aq1e
|
||||
title: Create weapon art preview component
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T12:22:54Z
|
||||
updated_at: 2026-01-14T13:48:27Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create a React component that displays 5 art pieces tagged with the weapon.
|
||||
|
||||
## Features
|
||||
|
||||
- Show 5 art pieces tagged with the weapon's slug
|
||||
- Each art shows: thumbnail, artist name
|
||||
- "View all" link to art page filtered by weapon tag
|
||||
|
||||
## Data Source
|
||||
|
||||
- `ArtRepository` with tag filter
|
||||
- Tag = weapon slug (canonical tag, e.g., "splattershot-jr")
|
||||
|
||||
## Props
|
||||
|
||||
- `artPieces` - array of 5 art objects
|
||||
- `weaponSlug` - for tag filtering and "view all" link
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Art uses existing tag system - weapon slug is the canonical tag
|
||||
- Reuse existing art display components if available
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
# sendou.ink-bp4w
|
||||
title: Replace trusted quick invite with friends quick invite
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:33:09Z
|
||||
updated_at: 2026-01-13T09:33:09Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Anywhere where user can currently quick invite their trusted users, now same can be done for friends (SendouQ, tournaments)
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
# sendou.ink-bti2
|
||||
title: Fix duplicate Notifications header in mobile user tab
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:39:53Z
|
||||
updated_at: 2026-01-11T13:02:44Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
On mobile, the user tab modal shows the "Notifications" header twice in a row - once as a section header and again immediately below it with a refresh button.
|
||||
|
||||
## Screenshot
|
||||
|
||||
The "You" modal displays:
|
||||
- User profile (Sendou)
|
||||
- 🔔 Notifications (first instance)
|
||||
- 🔔 Notifications + refresh button (second instance)
|
||||
- Notification list items
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The Notifications header should only appear once.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Only one Notifications header is displayed in the mobile user tab
|
||||
- Refresh functionality is preserved
|
||||
- Layout remains clean and properly structured
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-bxxe
|
||||
title: Improve expanded row border alignment style
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T15:23:48Z
|
||||
updated_at: 2026-01-13T15:23:48Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
Review the expanded row styling in the weapons page params table and see if the border alignment can be improved for a cleaner visual appearance.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-cml6
|
||||
title: Investigate visual regression test failures
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T15:06:10Z
|
||||
updated_at: 2026-01-11T15:09:14Z
|
||||
---
|
||||
|
||||
Investigate visual regression test failures and update fixtures if they seem expected based on the current css-rework-sidenav branch changes.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
# sendou.ink-d6vh
|
||||
title: My Events data layer
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T11:45:35Z
|
||||
updated_at: 2026-01-11T12:51:07Z
|
||||
parent: sendou.ink-om3i
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create the data fetching layer for the My Events page that combines tournaments and scrims into a unified event list.
|
||||
|
||||
## Details
|
||||
|
||||
**Data sources to combine:**
|
||||
- Tournaments user is registered for
|
||||
- Tournaments user is organizing
|
||||
- Scrims with scheduled matches
|
||||
- Scrims in looking-for-match state
|
||||
|
||||
**Output:**
|
||||
- Single sorted list of events (chronological)
|
||||
- Each event needs: name, time, status, type (tournament/scrim)
|
||||
- Tournament events need: check-in window info, handle two-day tournaments
|
||||
- Filter to upcoming events only (no past)
|
||||
|
||||
## Technical approach
|
||||
|
||||
- Create loader at `/my-events` route
|
||||
- Repository functions to fetch user tournaments and scrims
|
||||
- Merge and sort by start time
|
||||
- Design data structure that works for both page and sidebar (shared)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create repository function for user's upcoming tournaments
|
||||
- [ ] Create repository function for user's upcoming scrims
|
||||
- [ ] Create unified event type/interface
|
||||
- [ ] Create loader that combines and sorts events
|
||||
- [ ] Verify data structure works for sidebar consumption
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
# sendou.ink-eb17
|
||||
title: Add ad slots to new layout
|
||||
status: draft
|
||||
type: task
|
||||
created_at: 2026-01-11T09:29:25Z
|
||||
updated_at: 2026-01-11T09:29:25Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Task
|
||||
|
||||
Define and implement ad slot placements for the new sidebar/mobile layout.
|
||||
|
||||
## To Define
|
||||
|
||||
- Where should ads appear? (sidebar, content area, mobile panels?)
|
||||
- Ad sizes and formats
|
||||
- How do ads interact with sidebar collapse?
|
||||
- Mobile-specific ad placements
|
||||
- Integration with existing ad provider
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-ekv0
|
||||
title: Collapse sidenav button flashes on mobile page load
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-15T19:16:35Z
|
||||
updated_at: 2026-01-17T06:04:49Z
|
||||
---
|
||||
|
||||
The collapse sidenav button should not be visible on mobile at all, but it currently flashes briefly during page load before being hidden. It should not show even for a fraction of a second.
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
---
|
||||
# sendou.ink-f1rm
|
||||
title: Notifications with action buttons
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T10:13:18Z
|
||||
updated_at: 2026-01-13T10:13:18Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Extend the notification system to support inline action buttons. First use case: accept/decline friend requests directly from notification dropdown.
|
||||
|
||||
## Current State
|
||||
|
||||
Notifications are display-only - users must navigate to another page to take action.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Generic Action Support
|
||||
Notifications should support optional action buttons:
|
||||
- Primary action (e.g., "Accept")
|
||||
- Secondary action (e.g., "Decline")
|
||||
- Actions trigger API calls without page navigation
|
||||
- Notification updates/dismisses after action
|
||||
|
||||
### Friend Request Actions
|
||||
First implementation:
|
||||
- Friend request notification shows "Accept" and "Decline" buttons
|
||||
- Accept → creates friendship, dismisses notification
|
||||
- Decline → deletes request, dismisses notification
|
||||
|
||||
## Database Changes
|
||||
|
||||
Extend notification schema (if needed):
|
||||
```sql
|
||||
-- Option A: Store action metadata in notification
|
||||
ALTER TABLE Notification ADD COLUMN actionType TEXT;
|
||||
ALTER TABLE Notification ADD COLUMN actionData TEXT; -- JSON
|
||||
|
||||
-- Option B: Derive actions from notification type
|
||||
-- No schema change, handle in code based on notification type
|
||||
```
|
||||
|
||||
## UI Components
|
||||
|
||||
### NotificationItem
|
||||
- Conditionally render action buttons based on notification type
|
||||
- Loading state during action
|
||||
- Success/error feedback
|
||||
- Optimistic UI update
|
||||
|
||||
### Action Types (extensible)
|
||||
```typescript
|
||||
type NotificationAction = {
|
||||
type: "FRIEND_REQUEST";
|
||||
actions: ["accept", "decline"];
|
||||
} |
|
||||
// not part of this task, but for future can also be group_invite etc.
|
||||
{
|
||||
type: "GROUP_INVITE";
|
||||
actions: ["accept", "decline"];
|
||||
} // ... future types
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
New /notifications actions route.
|
||||
|
||||
## Future Use Cases
|
||||
|
||||
- Group invites (accept/decline)
|
||||
- Tournament team invites
|
||||
- Match ready check
|
||||
- Scrim requests
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Design notification action data model
|
||||
- [ ] Update NotificationItem component with action buttons
|
||||
- [ ] Action API endpoint or reuse existing endpoints
|
||||
- [ ] Loading/success/error states
|
||||
- [ ] Implement for friend requests
|
||||
- [ ] Update notification after action (dismiss or mark complete)
|
||||
- [ ] Mobile-friendly action buttons
|
||||
- [ ] Tests for notification actions
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
# sendou.ink-g01q
|
||||
title: Explore more comfortable way to close mobile tab menu panels
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-15T19:19:30Z
|
||||
updated_at: 2026-01-15T19:19:30Z
|
||||
---
|
||||
|
||||
The X button to close mobile tab menu panels is positioned far out of reach, making it uncomfortable to use.
|
||||
|
||||
## Potential solution
|
||||
React Aria's Sheet component might be a good approach: https://react-aria.adobe.com/examples/sheet
|
||||
|
||||
This would allow swipe-to-dismiss gestures which are more ergonomic on mobile.
|
||||
|
||||
## Trade-offs
|
||||
- Pro: Better UX with swipe gestures
|
||||
- Con: Requires pulling in a new dependency (Motion)
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
---
|
||||
# sendou.ink-gdrp
|
||||
title: Update trust-dependent features to use friendship
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:33:32Z
|
||||
updated_at: 2026-01-13T09:33:32Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Update all code that uses TrustRelationship to use Friendship instead.
|
||||
|
||||
## Files to Update
|
||||
|
||||
### SendouQ Group Adding
|
||||
- `app/features/sendouq/actions/q.preparing.server.ts` - ADD_TRUSTED action
|
||||
- `app/features/sendouq/components/MemberAdder.tsx` - Uses useTrusted hook
|
||||
- `app/hooks/swr.ts` - useTrusted() hook → useFriends()
|
||||
- `app/features/sendouq/routes/trusters.ts` - Trusters API → Friends API
|
||||
|
||||
### Tournament Join
|
||||
- `app/features/tournament/actions/to.$id.join.server.ts` - Trust checkbox on join
|
||||
- `app/features/tournament/loaders/to.$id.register.server.ts` - trusterPlayers query
|
||||
- Change "trust" checkbox to "add as friend" checkbox
|
||||
|
||||
### Scrim Pickups
|
||||
- `app/features/scrims/actions/scrims.new.server.ts` - Validates trusted for pickup
|
||||
- Update to check friendship instead
|
||||
|
||||
### Settings
|
||||
- `app/features/sendouq-settings/routes/q.settings.tsx` - Trusted users list
|
||||
- `app/features/sendouq-settings/QSettingsRepository.server.ts` - Trust queries
|
||||
- Replace with friends list/management
|
||||
|
||||
### Cleanup Routine
|
||||
- `app/routines/deleteOldTrusts.ts` - Delete after migration complete
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Update SendouQ ADD_TRUSTED to use friends
|
||||
- [ ] Update MemberAdder component
|
||||
- [ ] Replace useTrusted hook with useFriends
|
||||
- [ ] Update tournament join flow
|
||||
- [ ] Update scrim pickup validation
|
||||
- [ ] Update Q settings page
|
||||
- [ ] Update or remove trust cleanup routine
|
||||
- [ ] Search codebase for remaining TrustRelationship references
|
||||
- [ ] E2E tests for updated flows
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
---
|
||||
# sendou.ink-gjie
|
||||
title: Create parameter comparison table component
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T12:22:15Z
|
||||
updated_at: 2026-01-13T12:21:54Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create a React component that displays weapon parameters in a comparison table format. Use `Table` component
|
||||
|
||||
## Design
|
||||
|
||||
- **Rows** = parameters (raw keys, translated via i18n if available)
|
||||
- **Columns** = weapons in same category (e.g., all shooters)
|
||||
- **Current weapon pinned** - always visible, visually highlighted
|
||||
- **Patch history inline** - cells show current value + indicator if changed, expandable to see full history (patch + date)
|
||||
|
||||
## Props
|
||||
|
||||
- `weaponId` - current weapon
|
||||
- `categoryWeapons` - list of weapons in same category
|
||||
- `params` - parameter data with patch history
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Use CSS modules for styling
|
||||
- Consider horizontal scroll for many weapons
|
||||
- Expandable rows for patch history (click to expand)
|
||||
- Changed values should have visual indicator (icon or color)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-gk34
|
||||
title: Improve tournament search relevance
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T08:58:56Z
|
||||
updated_at: 2026-01-11T08:58:56Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
For tournament search results, when there are equally good matches, show tournaments closest to current date first. Example: searching 'In The Zone' should show newest tournament first. Location: app/features/search/routes/search.ts:86
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-govi
|
||||
title: Load test sidenav
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:28:34Z
|
||||
updated_at: 2026-01-11T12:28:34Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Perform load tests to ensure the sidenav performs well under various conditions and with different data volumes.
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-h8l0
|
||||
title: Fix MobileNav padding on Android
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-11T08:58:54Z
|
||||
updated_at: 2026-01-11T08:58:54Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The mobile navigation lacks proper padding on Android devices. iOS displays correctly. Location: app/components/MobileNav.tsx:35
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
# sendou.ink-h9ht
|
||||
title: Design and test prestige formula
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:21:17Z
|
||||
updated_at: 2026-01-12T09:21:23Z
|
||||
parent: sendou.ink-ylq5
|
||||
blocking:
|
||||
- sendou.ink-10ai
|
||||
---
|
||||
|
||||
Experiment with different prestige calculation formulas using real tournament data.
|
||||
|
||||
## Algorithm Concept (from epic)
|
||||
|
||||
Calculate prestige based on average seeding power of top 8 teams compared to a baseline.
|
||||
|
||||
## Variables to Experiment With
|
||||
|
||||
- Which teams to consider (top 8? top 4? all teams?)
|
||||
- Baseline value (median of all tournaments? fixed threshold?)
|
||||
- Team count weighting (16-team vs 128-team handling)
|
||||
- Continuous score vs discrete tiers
|
||||
|
||||
## Test Cases
|
||||
|
||||
Run formula against known tournaments and verify results match intuition:
|
||||
- Major community tournaments (should be high prestige)
|
||||
- Regular weeklies (should be medium)
|
||||
- Casual/new tournaments (should be lower)
|
||||
|
||||
## Output
|
||||
|
||||
- Documented formula with rationale
|
||||
- Test results showing formula produces expected rankings
|
||||
- Configuration constants for tuning
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Seeding data analysis (sendou.ink-XXX) for understanding data distribution
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
---
|
||||
# sendou.ink-hw3x
|
||||
title: Update sidebar to use real stream data
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-12T09:20:56Z
|
||||
updated_at: 2026-01-12T09:20:56Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Replace mock stream data in sidebar with real aggregated streams.
|
||||
|
||||
## Current State
|
||||
|
||||
- `/app/features/sidebar/routes/sidebar.ts` has `getMockStreams()`
|
||||
- Returns hardcoded test data
|
||||
- Sidebar already displays streams in correct format
|
||||
|
||||
## Requirements
|
||||
|
||||
- Call stream aggregation service
|
||||
- Apply scoring algorithm to get top 3
|
||||
- Return in SideNavLink format: `{ id, name, imageUrl, subtitle, badge }`
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Import aggregation service in sidebar.ts
|
||||
- [ ] Replace `getMockStreams()` with call to `aggregateStreams()`
|
||||
- [ ] Apply `rankStreams()` to get scored/shuffled order
|
||||
- [ ] Take top 3 streams
|
||||
- [ ] Map to SideNavLink format
|
||||
- [ ] Add error handling (return empty array if service fails)
|
||||
- [ ] Test with real Twitch data
|
||||
|
||||
## Implementation
|
||||
|
||||
```typescript
|
||||
// sidebar.ts loader
|
||||
import { aggregateStreams, rankStreams } from "~/features/streams/streams.server";
|
||||
|
||||
async function getStreams() {
|
||||
try {
|
||||
const allStreams = await aggregateStreams();
|
||||
const ranked = rankStreams(allStreams);
|
||||
return ranked.slice(0, 3).map(stream => ({
|
||||
id: stream.id,
|
||||
name: stream.name,
|
||||
imageUrl: stream.imageUrl,
|
||||
subtitle: stream.subtitle,
|
||||
badge: stream.badge,
|
||||
url: stream.url,
|
||||
}));
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch streams:", error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
- If aggregation service fails, return empty array (don't break sidebar)
|
||||
- Log error for debugging
|
||||
- Sidebar gracefully hides streams section when empty
|
||||
|
||||
## Dependencies
|
||||
|
||||
- sendou.ink-nw8b: Stream aggregation service
|
||||
- sendou.ink-js3r: Sidebar scoring algorithm
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
# sendou.ink-i6lm
|
||||
title: Radio buttons and similar components get squished on mobile
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-15T19:29:55Z
|
||||
updated_at: 2026-01-15T19:29:55Z
|
||||
---
|
||||
|
||||
Some components like radio buttons get squished when there is no horizontal space available on mobile devices. This affects usability and visual appearance on smaller screens.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
## Checklist
|
||||
|
||||
- [ ] Identify affected components (radio buttons, checkboxes, etc.)
|
||||
- [ ] Investigate root cause of squishing behavior
|
||||
- [ ] Implement fix to ensure components maintain minimum size
|
||||
- [ ] Test on various mobile viewport widths
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-iam7
|
||||
title: Replace placeholder logo
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T08:58:55Z
|
||||
updated_at: 2026-01-11T08:58:55Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Replace the placeholder logo with final logo asset when ready. Location: app/components/layout/index.tsx:259
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
---
|
||||
# sendou.ink-iulp
|
||||
title: FriendRepository implementation
|
||||
status: in-progress
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-13T09:32:05Z
|
||||
updated_at: 2026-01-16T07:59:43Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Create repository for friend-related database operations.
|
||||
|
||||
## File
|
||||
|
||||
`app/features/friends/FriendRepository.server.ts`
|
||||
|
||||
## Functions
|
||||
|
||||
### Friendship CRUD
|
||||
- `insert(userOneId, userTwoId)` - Create mutual friendship (ensure userOneId < userTwoId)
|
||||
- `delete(userId, friendId)` - Remove friendship
|
||||
- `findByUserId(userId)` - Get all friends for a user
|
||||
- `findMutualFriends(userIdA, userIdB)` - Get mutual friends between two users
|
||||
|
||||
### Friend Requests
|
||||
- `insert(senderId, receiverId)` - Send friend request
|
||||
- `delete(senderId, receiverId)` - Cancel/decline request
|
||||
- `findPendingForUser(userId)` - Get incoming requests
|
||||
- `findOutgoingForUser(userId)` - Get outgoing requests
|
||||
- `hasPendingRequest(senderId, receiverId)` - Check if request exists
|
||||
|
||||
### Connections (aggregated)
|
||||
- `findAllConnectionsWithActivity(userId)` - Get friends, teammates, associations with SendouQ/tournament activity
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Create FriendRepository.server.ts
|
||||
- [x] Implement `findByUserIdWithActivity(userId)` for sidebar
|
||||
- [ ] Implement friendship CRUD
|
||||
- [ ] Implement friend request operations
|
||||
- [ ] Unit tests for repository functions
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
---
|
||||
# sendou.ink-ivaf
|
||||
title: Friends section in sidebar with quick invite
|
||||
status: todo
|
||||
type: feature
|
||||
created_at: 2026-01-16T10:17:54Z
|
||||
updated_at: 2026-01-16T10:17:54Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Integrate friends into the sidebar, enabling quick invites and friend status viewing.
|
||||
|
||||
**Related:** sendou.ink-255r (Friends feature epic)
|
||||
|
||||
## Features
|
||||
|
||||
### Quick Invite
|
||||
- Users can send a "quick invite" to friends who have a partial SendouQ group that is currently looking for members
|
||||
- The invite should be fast/easy to send directly from the sidebar
|
||||
|
||||
### Expandable Friend Details
|
||||
When a user expands a friend entry in the sidebar, display:
|
||||
- User avatar
|
||||
- User name
|
||||
- Weapons (their current weapon pool or equipped weapons)
|
||||
- Current group info (if they're in a SendouQ group)
|
||||
- Any custom status text if available
|
||||
|
||||
For each of the friends groups' members
|
||||
|
||||
### Pending Requests Indicator
|
||||
- Show pending requests somewhere visible in the UI
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Design UI for friends list in sidebar
|
||||
- [ ] Add expand/collapse functionality for friend entries
|
||||
- [ ] Display friend details (avatar, name, weapons, status text)
|
||||
- [ ] Show current SendouQ group info for friends who are looking
|
||||
- [ ] Implement quick invite button for friends with partial groups
|
||||
- [ ] Add pending friend requests indicator
|
||||
- [ ] Handle loading and empty states
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
---
|
||||
# sendou.ink-j4zp
|
||||
title: Remove and redirect /u page
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:56Z
|
||||
updated_at: 2026-01-11T14:08:47Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Deprecate and remove the /u page. The /u page is a user search page that should be replaced by the CommandPalette search modal.
|
||||
|
||||
## Approach
|
||||
|
||||
Add URL search params to CommandPalette to allow opening it via a direct link:
|
||||
- `?search=open` - opens the CommandPalette modal
|
||||
- `?q=<query>` - pre-fills the search query
|
||||
- `?type=users|teams|organizations|tournaments` - sets the search type
|
||||
|
||||
Then redirect /u to /?search=open&type=users (preserving any existing `q` param).
|
||||
|
||||
## Files involved
|
||||
|
||||
- `app/components/layout/CommandPalette.tsx` - add search param support
|
||||
- `app/features/user-search/routes/u.tsx` - replace with redirect
|
||||
- `app/features/user-search/loaders/u.server.ts` - can be removed
|
||||
- `routes.ts` - update route to use redirect
|
||||
- navIconUrl (png and avif files)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Add search param support to CommandPalette (`search`, `q`, `type` params)
|
||||
- [x] Update /u route to redirect to /?search=open&type=users
|
||||
- [x] Remove unused loader and route components
|
||||
- [x] Remove any reference to u navIcon including breadcrumbs
|
||||
- [x] Remove from nav (was not in nav)
|
||||
- [ ] Test the redirect works correctly
|
||||
- [x] Run checks to ensure everything passes
|
||||
|
||||
## Additional changes
|
||||
|
||||
- Updated `UserSearch` component to use `/search` API instead of `/u`
|
||||
- Removed `USER_SEARCH_PAGE` constant from urls.ts
|
||||
- Removed "u" nav item from `nav-items.ts` and `TopNavMenus.tsx`
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
# sendou.ink-ja9h
|
||||
title: Show all notifications link doesn't close menu on mobile
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T19:22:01Z
|
||||
updated_at: 2026-01-12T15:32:45Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
On mobile, clicking the 'Show all notifications' link navigates to the notifications page in the background but doesn't close the menu/popover.
|
||||
|
||||
The menu should close when the page navigates.
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
---
|
||||
# sendou.ink-jesq
|
||||
title: Move front page data back to front page loader
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-25T12:05:14Z
|
||||
updated_at: 2026-01-25T12:05:14Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The commit 131fa699f moved front page specific data loading (ShowcaseTournaments.frontPageTournamentsByUserId, changelog, leaderboards) into root.tsx loader as part of the sidenav rework.
|
||||
|
||||
This data should be moved back to the front page loader (_index route) since it's only needed there, not on every page load.
|
||||
|
||||
## Context
|
||||
- Commit 131fa699f added this to root loader
|
||||
- Data includes: tournaments, changelog, leaderboards
|
||||
- Currently loaded via Promise.all in root loader
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
---
|
||||
# sendou.ink-jkq9
|
||||
title: Create mock Twitch streams service for development
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-12T12:21:36Z
|
||||
updated_at: 2026-01-12T12:21:36Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Create a mock streams service that simulates Twitch API responses for local development without requiring Twitch credentials.
|
||||
|
||||
## Why
|
||||
|
||||
- Develop stream features without Twitch API credentials
|
||||
- Faster iteration (no network calls)
|
||||
- Predictable test data
|
||||
- Works offline
|
||||
|
||||
## Requirements
|
||||
|
||||
- Same interface as real Twitch service (`getStreams()`)
|
||||
- Returns realistic mock data (usernames, thumbnails, viewer counts)
|
||||
- Configurable: number of streams, online/offline states
|
||||
- Easy toggle between mock and real service
|
||||
|
||||
## Options to Consider
|
||||
|
||||
1. **Simple mock function** - Just return hardcoded data in dev mode
|
||||
2. **JSON file** - Load mock data from a JSON file
|
||||
3. **json-server** - Separate mock server (may be overkill)
|
||||
4. **MSW (Mock Service Worker)** - Intercepts fetch calls (good for tests too)
|
||||
|
||||
## Recommendation
|
||||
|
||||
Start simple: environment variable toggle + mock function that returns static data.
|
||||
|
||||
```typescript
|
||||
// /app/modules/twitch/streams.ts
|
||||
export async function getStreams() {
|
||||
if (process.env.NODE_ENV === "development" && !process.env.TWITCH_CLIENT_ID) {
|
||||
return getMockStreams();
|
||||
}
|
||||
return getRealStreams();
|
||||
}
|
||||
|
||||
function getMockStreams(): MappedStream[] {
|
||||
return [
|
||||
{ twitchUserName: "sendou", viewerCount: 150, thumbnailUrl: "..." },
|
||||
{ twitchUserName: "teststreamer1", viewerCount: 89, thumbnailUrl: "..." },
|
||||
// ... more mock data
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
## Mock Data Should Include
|
||||
|
||||
- 5-10 mock streamers with realistic usernames
|
||||
- Variety of viewer counts (10 - 500 range)
|
||||
- Placeholder thumbnail URLs (or local images)
|
||||
- Some usernames matching seeded dev database users (if applicable)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add mock toggle logic to `/app/modules/twitch/streams.ts`
|
||||
- [ ] Create mock data with realistic stream info
|
||||
- [ ] Ensure mock works when TWITCH_CLIENT_ID is not set
|
||||
- [ ] Document in README or .env.example
|
||||
- [ ] Consider: sync mock usernames with seed data users
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
# sendou.ink-jopf
|
||||
title: 'Decide on front page content: proper feed or restore old layout'
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T09:47:05Z
|
||||
updated_at: 2026-01-11T09:47:05Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The front page needs attention - either build out a proper activity feed or restore the previous front page content for now.
|
||||
|
||||
## Options
|
||||
|
||||
### Option A: Build proper feed
|
||||
- Design and implement a real activity feed with relevant content
|
||||
- Would include things like: recent tournament results, friend activity, team updates, community highlights
|
||||
- More work but provides value
|
||||
|
||||
### Option B: Restore old front page
|
||||
- Bring back the previous front page content/layout
|
||||
- Quick solution to have something meaningful on the homepage
|
||||
- Can revisit feed implementation later
|
||||
|
||||
## Decision needed
|
||||
|
||||
Decide which approach to take based on timeline and priorities.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Decide on approach (feed vs restore old)
|
||||
- [ ] Implement chosen solution
|
||||
- [ ] Test on desktop and mobile
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
---
|
||||
# sendou.ink-js3r
|
||||
title: Implement sidebar scoring algorithm
|
||||
status: todo
|
||||
type: feature
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:20:16Z
|
||||
updated_at: 2026-01-12T09:21:32Z
|
||||
parent: sendou.ink-r6ry
|
||||
blocking:
|
||||
- sendou.ink-hw3x
|
||||
---
|
||||
|
||||
Create the scoring algorithm that determines which streams appear in the sidebar (top 3).
|
||||
|
||||
## Scoring Principles
|
||||
|
||||
- Skill-based ranking only (NO viewer count)
|
||||
- Configurable weights for easy tuning
|
||||
|
||||
## Scoring by Source
|
||||
|
||||
### Tournament streams
|
||||
- Base: Tournament prestige score (from prestige epic)
|
||||
- Bonus: Round progression (later rounds score higher)
|
||||
- Fallback until prestige system: Simple heuristics (team count tiers)
|
||||
|
||||
### SendouQ streams
|
||||
- Score based on tier/peak XP
|
||||
- Existing tier logic in /app/features/sendouq-streams/
|
||||
|
||||
### Calendar event streams
|
||||
- Fixed score (e.g., 500 - tune based on testing)
|
||||
- Simple approach for now, can add event-based scoring later
|
||||
|
||||
### Non-match streamers
|
||||
- Score by peak XP from linked X rank account
|
||||
|
||||
## Daily Shuffle
|
||||
|
||||
- Seeded random by date (consistent order for the day)
|
||||
- Higher skill weighted more heavily
|
||||
- Lower skill still has chance to appear
|
||||
|
||||
Example algorithm:
|
||||
```typescript
|
||||
// Seed based on date for consistency
|
||||
const seed = dateFns.startOfDay(new Date()).getTime();
|
||||
const rng = seedrandom(seed.toString());
|
||||
|
||||
// Weighted shuffle: multiply score by random factor
|
||||
const shuffled = streams.map(s => ({
|
||||
...s,
|
||||
sortScore: s.score * (0.5 + rng() * 0.5) // 50-100% of score
|
||||
}));
|
||||
shuffled.sort((a, b) => b.sortScore - a.sortScore);
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create `scoreStream()` function for individual stream scoring
|
||||
- [ ] Create `rankStreams()` function that applies daily shuffle
|
||||
- [ ] Define score constants at top of file (easy to tune)
|
||||
- [ ] Add tournament fallback scoring (team count tiers until prestige exists)
|
||||
- [ ] Add round progression bonus mapping
|
||||
- [ ] Test with real data to verify reasonable distribution
|
||||
|
||||
## Score Constants (starting point)
|
||||
|
||||
```typescript
|
||||
const SCORES = {
|
||||
// Tournament base by team count
|
||||
TOURNAMENT_16_PLUS: 1000,
|
||||
TOURNAMENT_8_PLUS: 800,
|
||||
TOURNAMENT_SMALL: 600,
|
||||
|
||||
// Round bonuses
|
||||
ROUND_FINALS: 200,
|
||||
ROUND_SEMIS: 150,
|
||||
ROUND_QUARTERS: 100,
|
||||
|
||||
// Calendar event (fixed)
|
||||
CALENDAR_EVENT: 500,
|
||||
|
||||
// SendouQ by tier (use existing tier values)
|
||||
// Non-match: use peak XP directly (already ~1500-3000 range)
|
||||
};
|
||||
```
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Make weights configurable (constants at top of file)
|
||||
- Document the scoring formula clearly
|
||||
- Lives in `/app/features/streams/scoring.server.ts`
|
||||
- Consider A/B testing different weight configurations later
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
---
|
||||
# sendou.ink-kluy
|
||||
title: Deprecate TrustRelationship table
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:33:39Z
|
||||
updated_at: 2026-01-13T09:33:39Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Final cleanup: remove TrustRelationship table after migration is stable.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Migration complete (sendou.ink-vd9w)
|
||||
- All trust-dependent features updated (sendou.ink-gdrp)
|
||||
- Stable in production for at least 1 week
|
||||
|
||||
## Steps
|
||||
|
||||
1. Remove TrustRelationship from `app/db/tables.ts`
|
||||
2. Create migration to drop table
|
||||
3. Remove `app/features/tournament/queries/giveTrust.server.ts`
|
||||
4. Remove `app/routines/deleteOldTrusts.ts`
|
||||
5. Remove any remaining trust-related code
|
||||
6. Update tests
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Confirm migration stable in production
|
||||
- [ ] Remove table definition from tables.ts
|
||||
- [ ] Create DROP TABLE migration
|
||||
- [ ] Remove giveTrust.server.ts
|
||||
- [ ] Remove deleteOldTrusts.ts routine
|
||||
- [ ] Search and remove remaining trust code
|
||||
- [ ] Update/remove trust-related tests
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
---
|
||||
# sendou.ink-kp16
|
||||
title: Map pool picker checkmark styling broken & tiebreak text hard to read
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-13T15:13:02Z
|
||||
updated_at: 2026-01-13T15:13:02Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
The map pool picker component has two styling issues:
|
||||
|
||||
1. **Checkmark styling is broken** - The checkmarks on selected maps (e.g., Inkblot Art Academy, MakoMart) appear to have incorrect styling
|
||||
2. **Tiebreak text is hard to read** - The "TIEBREAK" text overlay has poor contrast/readability against the map image background
|
||||
|
||||
## Expected behavior
|
||||
|
||||
- Checkmarks should have consistent, visible styling that matches the design system
|
||||
- Tiebreak text should have sufficient contrast to be easily readable (similar to the "BANNED" text which appears more visible)
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
# sendou.ink-kph0
|
||||
title: Deprecate /q/streams with redirect
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-12T09:20:46Z
|
||||
updated_at: 2026-01-12T09:20:46Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Remove the old /q/streams page and redirect to unified /streams page.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Redirect /q/streams to /streams?source=sendouq
|
||||
- Remove link from /q/looking page
|
||||
- Keep redirect permanent (301)
|
||||
|
||||
## Files to Update
|
||||
|
||||
- /app/features/sendouq-streams/routes/q.streams.tsx - convert to redirect
|
||||
- /app/features/sendouq/routes/q.looking.tsx - remove streams link
|
||||
- routes.ts - may need route changes
|
||||
|
||||
## Notes
|
||||
|
||||
- Should be done in same release as /streams page launch
|
||||
- Preserve any bookmarked URLs via redirect
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
---
|
||||
# sendou.ink-kvrh
|
||||
title: Weapon art 'View all' link should support multiple tag variations
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-14T16:01:57Z
|
||||
updated_at: 2026-01-14T16:01:57Z
|
||||
---
|
||||
|
||||
The WeaponArtPreview component's 'View all' link currently only links to one tag (the slug with hyphens, e.g. `/art?tag=luna-blaster`). However, the art query searches for multiple tag variations (hyphens, spaces, underscores).
|
||||
|
||||
Consider:
|
||||
- Updating the art page to support multiple tag filters
|
||||
- Or showing all matching tag variations in the link
|
||||
- Or consolidating duplicate tags in the database
|
||||
|
||||
Related: WeaponArtPreview component in app/features/weapons/components/WeaponArtPreview.tsx
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
# sendou.ink-kw6u
|
||||
title: Show scrims in Events
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
tags:
|
||||
- my-events-epic
|
||||
created_at: 2026-01-11T09:44:26Z
|
||||
updated_at: 2026-01-13T16:21:09Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Display scrims (both scheduled and looking-for-match) in the sidebar's "Events" section.
|
||||
|
||||
## Details
|
||||
|
||||
The Events section currently shows tournament calendar entries. It should also include:
|
||||
|
||||
1. **Scheduled scrims** - Scrims where the user's team has a confirmed match scheduled
|
||||
2. **Looking-for-match scrims** - Active scrim postings where user's team is still searching for opponents
|
||||
|
||||
This gives competitive players visibility into their upcoming scrim commitments directly from the sidebar, reducing the need to navigate to a separate scrims page.
|
||||
|
||||
## Checklist
|
||||
|
||||
- [x] Identify where scrim data is fetched/stored
|
||||
- [x] Add `findUserScrims` repository function
|
||||
- [x] Update sidebar loader to fetch and merge scrims
|
||||
- [x] Update Layout component to render scrims with badges
|
||||
- [x] Add badge variant to SideNav component
|
||||
- [x] Add CSS for "looking" badge variant
|
||||
- [x] Add translation keys
|
||||
- [x] Test with various scrim states
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
---
|
||||
# sendou.ink-lk5i
|
||||
title: Profile page friend button
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:32:51Z
|
||||
updated_at: 2026-01-13T09:32:51Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Add friend request button to user profile pages. IMPORTANT need to be added both to the old user profile and new user profile (widget based).
|
||||
|
||||
## Location
|
||||
|
||||
`app/features/user-page/routes/u.$identifier.tsx` (or similar profile route)
|
||||
|
||||
## States
|
||||
|
||||
Button shows different states based on relationship:
|
||||
1. **Not friends, no request**: "Add Friend" button → sends request
|
||||
2. **Outgoing request pending**: "Request Sent" (disabled or cancel option)
|
||||
3. **Incoming request pending**: "Accept Request" / "Decline" buttons
|
||||
4. **Already friends**: "Friends ✓" with unfriend option in dropdown
|
||||
|
||||
## Implementation
|
||||
|
||||
- Check friendship status in loader
|
||||
- Check pending requests in both directions
|
||||
- Action handler for send/accept/decline/unfriend
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add friendship status to profile loader
|
||||
- [ ] Friend button component with all states
|
||||
- [ ] Action handlers for friend operations
|
||||
- [ ] Loading states during actions
|
||||
- [ ] Success/error feedback
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
---
|
||||
# sendou.ink-m9lp
|
||||
title: Friend checkbox on invite link join
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:33:50Z
|
||||
updated_at: 2026-01-13T09:33:50Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Update the invite link join flow to offer friending instead of trusting.
|
||||
|
||||
## Current Flow
|
||||
|
||||
When joining SendouQ group or tournament team via invite link:
|
||||
- Checkbox: "Trust [owner name]"
|
||||
- If checked, creates TrustRelationship
|
||||
|
||||
## New Flow
|
||||
|
||||
- Checkbox: "Send friend request to [owner name]"
|
||||
- If checked, creates FriendRequest (not immediate friendship)
|
||||
- Or if they already sent you a request, accepts it (creates friendship)
|
||||
|
||||
## Files
|
||||
|
||||
- `app/features/sendouq/actions/q.server.ts` - JOIN_TEAM_WITH_TRUST action
|
||||
- `app/features/tournament/actions/to.$id.join.server.ts` - Trust checkbox handling
|
||||
- Related UI components for the join forms
|
||||
|
||||
## Behavior
|
||||
|
||||
1. If not friends and no pending request: create FriendRequest from joiner → owner
|
||||
2. If pending request from owner → joiner: accept request, create Friendship
|
||||
3. If already friends: no-op
|
||||
4. Notification sent to owner
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Update SendouQ join action
|
||||
- [ ] Update tournament join action
|
||||
- [ ] Update checkbox labels (i18n)
|
||||
- [ ] Handle mutual request → friendship case
|
||||
- [ ] Tests for join flow
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
---
|
||||
# sendou.ink-n3wk
|
||||
title: Rename mobile menu tab from Calendar to avoid confusion
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:38:36Z
|
||||
updated_at: 2026-01-11T12:48:03Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
On mobile, the bottom tab bar has a calendar icon labeled "Calendar" that opens the menu/navigation modal. This is confusing because there is an actual Calendar page in the app, and users may expect tapping "Calendar" to navigate there.
|
||||
|
||||
## Screenshot
|
||||
|
||||
The bottom tab shows a calendar icon with "Calendar" label, but it functions as the menu button.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The menu tab should have a label that clearly indicates it opens navigation/menu, not the Calendar page.
|
||||
|
||||
## Possible solutions
|
||||
|
||||
- Rename to "My Calendar" (check if fits)
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Mobile menu tab label clearly communicates its function
|
||||
- No confusion with the actual Calendar page
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
---
|
||||
# sendou.ink-nucy
|
||||
title: Consistent avatar border radius in sidebar
|
||||
status: draft
|
||||
type: feature
|
||||
created_at: 2026-01-16T09:23:10Z
|
||||
updated_at: 2026-01-16T09:23:10Z
|
||||
---
|
||||
|
||||
Currently sidebar avatars have inconsistent border radius styles:
|
||||
- Some are fully rounded (circle)
|
||||
- Some are slightly rounded
|
||||
- Some have no background/different treatment
|
||||
|
||||
## Idea
|
||||
|
||||
Add a theme option for avatar border radius that applies globally to all avatars:
|
||||
- **round** - fully circular (border-radius: 50%)
|
||||
- **rounded** - slightly rounded corners
|
||||
- **square** - no border radius
|
||||
|
||||
This would provide visual consistency and give users control over their preferred avatar style.
|
||||
|
||||
## Alternative
|
||||
|
||||
Choose one and apply everywhere.
|
||||
|
||||
## Areas to check
|
||||
- Tournament/event avatars in sidebar
|
||||
- Friend list avatars
|
||||
- User avatars throughout the app
|
||||
- Team avatars
|
||||
|
||||
## Checklist
|
||||
- [ ] Audit current avatar border radius usage across codebase
|
||||
- [ ] Design CSS variable approach for avatar border radius
|
||||
- [ ] Add theme option to settings
|
||||
- [ ] Apply consistent border radius to all Avatar components
|
||||
- [ ] Test across different contexts (sidebar, profiles, etc.)
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
---
|
||||
# sendou.ink-nw8b
|
||||
title: Implement stream aggregation service
|
||||
status: todo
|
||||
type: feature
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:20:06Z
|
||||
updated_at: 2026-01-12T09:21:32Z
|
||||
parent: sendou.ink-r6ry
|
||||
blocking:
|
||||
- sendou.ink-hw3x
|
||||
---
|
||||
|
||||
Create a unified service that combines streams from all sources into a single sorted list.
|
||||
|
||||
## Stream Sources
|
||||
|
||||
### 1. SendouQ matches
|
||||
- Players in active matches who are streaming
|
||||
- Existing: `/app/features/sendouq-streams/core/streams.server.ts`
|
||||
- Reuse `streamedMatches()` function
|
||||
|
||||
### 2. Tournament matches
|
||||
- Players/casters streaming tournament matches
|
||||
- Existing: `/app/features/tournament/core/streams.server.ts`
|
||||
- Reuse `streamsByTournamentId()` function
|
||||
- Include round name (e.g., 'Top 8', 'Grand Finals')
|
||||
- Group streams of the same match together
|
||||
|
||||
### 3. Calendar event streams (new)
|
||||
- External events with curator-added stream links
|
||||
- Query CalendarEventStream table for upcoming events
|
||||
- These are just URLs - may not be live (display "Upcoming" not "LIVE")
|
||||
- Soft dependency on sendou.ink-a9gl (can skip if not done yet)
|
||||
|
||||
### 4. Non-match streamers (new)
|
||||
- Players streaming Splatoon 3 but NOT in SQ/tournament matches
|
||||
- **Must have X rank account linked** (SplatoonPlayer with userId set)
|
||||
- Sorted by peak XP from X rank data
|
||||
- Filter out anyone already appearing in sources 1-2
|
||||
|
||||
## Output Type
|
||||
|
||||
```typescript
|
||||
interface AggregatedStream {
|
||||
id: string; // Unique identifier
|
||||
name: string; // Display name
|
||||
imageUrl: string; // Thumbnail or avatar
|
||||
subtitle: string; // Round name, scheduled time, etc.
|
||||
badge?: "LIVE" | "UPCOMING"; // Status badge
|
||||
source: "sendouq" | "tournament" | "calendar" | "general";
|
||||
score: number; // For sorting (from scoring algorithm)
|
||||
url: string; // Link to stream
|
||||
twitchUsername?: string; // For Twitch embeds
|
||||
}
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create `/app/features/streams/` folder structure
|
||||
- [ ] Create `aggregateStreams()` main function in `streams.server.ts`
|
||||
- [ ] Implement SendouQ source adapter
|
||||
- [ ] Implement Tournament source adapter
|
||||
- [ ] Implement Calendar event source adapter (can be empty initially)
|
||||
- [ ] Implement non-match streamers source (users with X rank + Twitch, currently streaming Splatoon 3)
|
||||
- [ ] Add type definitions
|
||||
- [ ] Add caching strategy (reuse Twitch's 2min cache pattern)
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- Create in `/app/features/streams/` (new feature folder)
|
||||
- Reuse existing Twitch caching via `/app/modules/twitch/`
|
||||
- Call existing stream functions, don't duplicate Twitch API logic
|
||||
- Non-match streamers query pattern:
|
||||
1. Get all Splatoon 3 streams from Twitch API
|
||||
2. Get users with `twitchUsername` AND linked `SplatoonPlayer` (X rank data)
|
||||
3. Match streams to users
|
||||
4. Filter out those already in SQ/tournament streams
|
||||
5. Sort by peak XP
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
# sendou.ink-o3l0
|
||||
title: Improve notifications popover top bar styling
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T11:51:53Z
|
||||
updated_at: 2026-01-11T11:51:53Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
The notifications popover top bar has styling issues:
|
||||
|
||||
1. **Lacks padding** - The header area needs proper padding for visual balance
|
||||
2. **Refresh icon too large** - The refresh/reload icon appears oversized compared to the title text
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add appropriate padding to the top bar header
|
||||
- [ ] Reduce the size of the refresh icon to match the title text better
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
---
|
||||
# sendou.ink-oiw2
|
||||
title: My Events navigation links
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T11:45:36Z
|
||||
updated_at: 2026-01-11T12:50:48Z
|
||||
parent: sendou.ink-om3i
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Add links to My Events page in sidebar (desktop) and mobile menu.
|
||||
|
||||
## Details
|
||||
|
||||
**Desktop sidebar:**
|
||||
- Add "My Events" link
|
||||
- Placement TBD (near existing Calendar link?)
|
||||
- Only show when logged in
|
||||
|
||||
**Mobile menu:**
|
||||
- Add "My Events" link in appropriate location
|
||||
- Only show when logged in
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add My Events link to desktop sidebar
|
||||
- [ ] Add My Events link to mobile menu
|
||||
- [ ] Ensure links only appear when authenticated
|
||||
- [ ] Add translations for link text
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
---
|
||||
# sendou.ink-om3i
|
||||
title: My Events page
|
||||
status: todo
|
||||
type: epic
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:45:51Z
|
||||
updated_at: 2026-01-11T12:55:40Z
|
||||
blocking:
|
||||
- sendou.ink-u4ag
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
A dedicated page (`/my-events`) for viewing the user's personal events with all their upcoming commitments in one centralized view.
|
||||
|
||||
## Why
|
||||
|
||||
Users struggle to see all their commitments (tournaments, scrims) in one place. While the sidebar shows a quick glance, players need a full page view to see their complete schedule.
|
||||
|
||||
## Scope (Initial)
|
||||
|
||||
**Must have:**
|
||||
- Tournaments user is registered for
|
||||
- Tournaments user is organizing
|
||||
- Scrims (scheduled matches)
|
||||
- Scrims (looking-for-match posts)
|
||||
|
||||
**Future consideration:**
|
||||
- SendouQ sessions
|
||||
- Team practice times
|
||||
- External calendar integration (Google, etc.)
|
||||
|
||||
## Design
|
||||
|
||||
**View format:** Simple list view, grouped by day (chronological)
|
||||
|
||||
**Event card info:**
|
||||
- Name (tournament name or scrim opponent)
|
||||
- Time
|
||||
- Status
|
||||
- Check-in window (for tournaments, e.g. "Check-in opens in 2 hours")
|
||||
- Handle two-day tournaments appropriately
|
||||
|
||||
**Time range:** All upcoming events only, no past events
|
||||
|
||||
**Interaction:** Clicking an event navigates directly to the tournament/scrim page
|
||||
|
||||
**URL:** `/my-events` (login required)
|
||||
|
||||
**Empty state:** Simple message ("No upcoming events") with links to /calendar and /scrims
|
||||
|
||||
**iCal export:** Support .ics file export for subscribing in external calendars (similar to existing /calendar feature)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Share components and data fetching logic with sidebar "Events" section
|
||||
- Related tasks: `sendou.ink-kw6u` (scrims in sidebar), `sendou.ink-1kb8` (times on mobile panel)
|
||||
|
||||
## Navigation
|
||||
|
||||
- Add link to sidebar (desktop)
|
||||
- Add link to mobile menu
|
||||
|
||||
## Completion Criteria
|
||||
|
||||
All child tasks resolved.
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
---
|
||||
# sendou.ink-p9v1
|
||||
title: Create npm script to sync weapon params from Leanny/splat3
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T12:22:15Z
|
||||
updated_at: 2026-01-13T12:04:46Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create an npm script (`npm run sync-weapon-params`) that fetches weapon parameter data from https://github.com/Leanny/splat3 and transforms it into sendou.ink's format.
|
||||
|
||||
## Output Format
|
||||
|
||||
JSON files stored in the repo. For parameters that changed across patches, use patch-keyed format:
|
||||
|
||||
```json
|
||||
{
|
||||
"damage": 36,
|
||||
"damage@5.0.0": 32,
|
||||
"damage@4.0.0": 30,
|
||||
"range": 50
|
||||
}
|
||||
```
|
||||
|
||||
- Plain key = current value
|
||||
- `key@patch` = historical value from that patch
|
||||
|
||||
## Requirements
|
||||
|
||||
- Fetch data from Leanny's repo (all weapon categories)
|
||||
- Track patch history by comparing versions
|
||||
- Output one JSON file per weapon or per category (TBD based on Leanny's structure)
|
||||
- Store in appropriate location (e.g., `app/features/weapons/data/`)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Examine Leanny's repo structure to understand data format
|
||||
- Script should be idempotent - running multiple times produces same result
|
||||
- Consider storing patch metadata (dates) separately
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-pspr
|
||||
title: Unit test sidenav data loading
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:28:34Z
|
||||
updated_at: 2026-01-11T12:28:34Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Write Vitest unit tests for sidenav data loading logic including loader functions and data transformations.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
---
|
||||
# sendou.ink-qu4s
|
||||
title: Show team and association members in friends section
|
||||
status: todo
|
||||
type: feature
|
||||
created_at: 2026-01-16T10:20:57Z
|
||||
updated_at: 2026-01-16T10:20:57Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
Extend the friends section in the sidebar to also display:
|
||||
- Team members (from the user's team)
|
||||
- Association members (from the user's association)
|
||||
|
||||
## Sorting priority
|
||||
Friends should appear first in the list, followed by team members, then association members.
|
||||
|
||||
## Checklist
|
||||
- [ ] Query team members for the current user
|
||||
- [ ] Query association members for the current user
|
||||
- [ ] Combine friends, team members, and association members into a single list
|
||||
- [ ] Implement sorting logic: friends first, then team, then association
|
||||
- [ ] Handle duplicate entries (e.g., a friend who is also a team member should only appear once, as a friend)
|
||||
- [ ] Update sidebar UI to display the combined list
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
---
|
||||
# sendou.ink-qwz1
|
||||
title: Fix admin page input widths
|
||||
status: draft
|
||||
type: task
|
||||
created_at: 2026-01-11T12:59:32Z
|
||||
updated_at: 2026-01-11T12:59:32Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
The admin page has inconsistent input widths - some inputs extend too wide while others are narrow (like the User dropdowns).
|
||||
|
||||
**Note:** With the incoming form rework, we might do a bigger overhaul of the admin UI anyway. This task may become part of that larger effort.
|
||||
|
||||
## Context
|
||||
- "Impersonate user" text input stretches full width
|
||||
- "Link player" User dropdown is very narrow compared to the Player ID input
|
||||
- "Add as artist" and "Give video adder" User dropdowns are also narrow
|
||||
- Overall form layout could be more consistent
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
---
|
||||
# sendou.ink-r6ry
|
||||
title: Streams integration in sidebar
|
||||
status: todo
|
||||
type: epic
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:18:00Z
|
||||
updated_at: 2026-01-12T08:49:38Z
|
||||
---
|
||||
|
||||
Unified streams experience across sendou.ink - displaying live and upcoming Splatoon community streams in the sidebar, mobile menu, and a dedicated /streams page.
|
||||
|
||||
## Goals
|
||||
|
||||
1. Surface live community streams prominently in the sidebar/mobile menu
|
||||
2. Create a central `/streams` page for browsing all current and upcoming streams
|
||||
3. Unify SendouQ, tournament, and community event streams under one system
|
||||
4. Deprecate fragmented stream pages (`/q/streams`, `/to/:id/streams`)
|
||||
|
||||
## Stream Sources
|
||||
|
||||
### 1. SendouQ Matches
|
||||
- Players in active SendouQ matches who are streaming
|
||||
- Scoring based on tier/peak XP
|
||||
- Already implemented in `/app/features/sendouq-streams/`
|
||||
|
||||
### 2. Tournament Matches
|
||||
- Players/casters streaming tournament matches
|
||||
- Scoring based on tournament prestige (separate epic) + round progression
|
||||
- Round names should be visible (e.g., "Top 8", "Grand Finals")
|
||||
- Streams of the same match should be visually grouped
|
||||
- Already partially implemented in `/app/features/tournament/core/streams.server.ts`
|
||||
|
||||
### 3. Calendar Event Streams (New)
|
||||
- External events (e.g., LANs) not hosted on sendou.ink
|
||||
- Requires new `STREAM_CURATOR` role (granted by staff)
|
||||
- Curators can only add stream links to events they created
|
||||
- Stream links are platform-agnostic URLs (Twitch, YouTube, etc.)
|
||||
- New CalendarEventStream join table for multiple links per event
|
||||
|
||||
### 4. Non-Match Streamers
|
||||
- Players streaming Splatoon but not in SQ/tournament
|
||||
- Must have X rank account linked
|
||||
- Sorted by peak XP
|
||||
|
||||
## Sidebar & Mobile Menu
|
||||
|
||||
### Display
|
||||
- Show top 3 streams (constant, easy to change later)
|
||||
- Use existing SideNavLink format:
|
||||
- Image (thumbnail/logo)
|
||||
- Name (tournament/streamer name)
|
||||
- Subtitle (round name, or scheduled time for upcoming)
|
||||
- Badge ("LIVE" indicator)
|
||||
- Link to `/streams` page
|
||||
|
||||
### Scoring Algorithm
|
||||
- Skill-based ranking only (no viewer count)
|
||||
- Configurable weights for easy tuning:
|
||||
- Tournament: prestige score + round progression bonus (fallback: team count tiers)
|
||||
- SendouQ: tier/peak XP
|
||||
- Calendar events: Fixed score (simple for now)
|
||||
- Non-match streamers: peak XP
|
||||
- Daily shuffle with bias toward higher score
|
||||
- Seeded random by date so order is consistent for the day
|
||||
- Higher scores weighted more heavily but lower scores still have chance to appear
|
||||
|
||||
### Update Strategy
|
||||
- Separate task exists for defining sidebar data update strategy (sendou.ink-wn5o)
|
||||
|
||||
## /streams Page
|
||||
|
||||
### Layout
|
||||
- Two sections: Current/Live streams and Upcoming streams
|
||||
- Desktop: potentially two-column layout (TBD in design phase)
|
||||
- Option to view merged list or grouped by source (SQ/Tournaments/Events)
|
||||
|
||||
### Current/Live Section
|
||||
- All active streams from all sources
|
||||
- Tournament streams sorted by round, grouped by match
|
||||
- Multiple tournaments interleaved by prestige/round score
|
||||
|
||||
### Upcoming Section
|
||||
- Calendar events with attached stream info
|
||||
- Tournaments with known start times
|
||||
- Future: scheduled league matches
|
||||
|
||||
### Twitch Embeds
|
||||
- Clicking a stream expands inline embed (accordion style)
|
||||
- Multiple embeds can be open simultaneously
|
||||
- Optional chat toggle alongside video
|
||||
|
||||
## Deprecations (Same Release)
|
||||
|
||||
### /q/streams
|
||||
- Redirect to `/streams?source=sendouq`
|
||||
- Remove link from `/q/looking` page
|
||||
|
||||
### /to/:id/streams
|
||||
- Redirect to `/streams?tournament=:id` (or similar filter)
|
||||
- Tournament bracket LIVE popovers retain current behavior (no change)
|
||||
|
||||
## New Permissions
|
||||
|
||||
### STREAM_CURATOR Role
|
||||
- New role in existing permissions system
|
||||
- Granted by staff (same flow as "is artist" role)
|
||||
- Allows adding stream links to calendar events user created
|
||||
- Scoped to own events only
|
||||
- Database: `isStreamCurator` boolean column on User table
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **sendou.ink-ylq5 - Tournament Prestige System**: Algorithm for calculating tournament prestige based on registered players' seeding power. Streams epic can start with simple heuristics (e.g., team count tiers) until prestige system is built. (soft dependency - can proceed without)
|
||||
|
||||
## Data Model Changes
|
||||
|
||||
### New Table: CalendarEventStream
|
||||
- Join table for calendar event stream links
|
||||
- Columns: id, calendarEventId, url
|
||||
- Supports multiple stream links per event (Twitch, YouTube, etc.)
|
||||
|
||||
### User Table
|
||||
- Add `isStreamCurator` boolean column (like `isArtist`)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Existing Infrastructure
|
||||
- Twitch API integration exists (`/app/modules/twitch/`)
|
||||
- Stream caching with 2-min cache, 10-min stale-while-revalidate
|
||||
- SendouQ streams logic in `/app/features/sendouq-streams/`
|
||||
- Tournament streams logic in `/app/features/tournament/core/streams.server.ts`
|
||||
|
||||
### Sidebar Integration
|
||||
- Current mock data in `/app/features/sidebar/routes/sidebar.ts`
|
||||
- Replace `getMockStreams()` with real stream aggregation
|
||||
|
||||
## Open Questions (To Resolve During Implementation)
|
||||
|
||||
1. ~~Calendar event stream scoring weight~~ → Fixed score (resolved)
|
||||
2. Exact layout for /streams page (start simple, iterate)
|
||||
3. Visual design for tournament match grouping
|
||||
4. Round ordering: progression order (R1→Finals) or reverse (Finals first)?
|
||||
5. Cross-tournament interleaving vs grouping by tournament
|
||||
|
||||
## Child Tasks
|
||||
|
||||
All child tasks have been created as separate tickets under this epic:
|
||||
|
||||
- sendou.ink-9cpl: Create /streams page route and basic layout
|
||||
- sendou.ink-nw8b: Implement stream aggregation service
|
||||
- sendou.ink-js3r: Implement sidebar scoring algorithm
|
||||
- sendou.ink-4m0t: Add STREAM_CURATOR role to permissions
|
||||
- sendou.ink-a9gl: Add Twitch channel field to CalendarEvent
|
||||
- sendou.ink-x535: Add stream curator UI for calendar events
|
||||
- sendou.ink-r717: Implement Twitch embed component with chat toggle
|
||||
- sendou.ink-kph0: Deprecate /q/streams with redirect
|
||||
- sendou.ink-u6b2: Deprecate /to/:id/streams with redirect
|
||||
- sendou.ink-hw3x: Update sidebar to use real stream data
|
||||
- sendou.ink-ae15: Add /streams link to sidebar and mobile menu
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
---
|
||||
# sendou.ink-r717
|
||||
title: Implement Twitch embed component with chat toggle
|
||||
status: todo
|
||||
type: feature
|
||||
created_at: 2026-01-12T09:20:45Z
|
||||
updated_at: 2026-01-12T09:20:45Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Create reusable Twitch embed component for the /streams page.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Clicking a stream expands inline embed (accordion style)
|
||||
- Multiple embeds can be open simultaneously
|
||||
- Optional chat toggle alongside video
|
||||
- Responsive sizing (16:9 aspect ratio)
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create `/app/components/TwitchEmbed.tsx` component
|
||||
- [ ] Implement video-only embed mode
|
||||
- [ ] Implement video + chat side-by-side mode
|
||||
- [ ] Add chat toggle button
|
||||
- [ ] Save chat preference to localStorage (`twitch-chat-enabled`)
|
||||
- [ ] Handle parent domain from `VITE_SITE_DOMAIN` env var
|
||||
- [ ] Add loading state while iframe loads
|
||||
- [ ] Test on mobile (responsive width)
|
||||
|
||||
## Component API
|
||||
|
||||
```tsx
|
||||
interface TwitchEmbedProps {
|
||||
channel: string; // Twitch username
|
||||
showChat?: boolean; // Default from localStorage
|
||||
onChatToggle?: (show: boolean) => void;
|
||||
}
|
||||
|
||||
// Usage
|
||||
<TwitchEmbed channel="sendou" />
|
||||
```
|
||||
|
||||
## Twitch Embed URL Format
|
||||
|
||||
```
|
||||
Video only:
|
||||
https://player.twitch.tv/?channel={channel}&parent={domain}&muted=false
|
||||
|
||||
Chat only:
|
||||
https://www.twitch.tv/embed/{channel}/chat?parent={domain}
|
||||
```
|
||||
|
||||
## Parent Domain
|
||||
|
||||
Twitch requires the `parent` parameter for embeds to work. Use:
|
||||
- `import.meta.env.VITE_SITE_DOMAIN` (strips protocol)
|
||||
- Parse hostname: `new URL(VITE_SITE_DOMAIN).hostname`
|
||||
- For localhost: `localhost`
|
||||
- For production: `sendou.ink`
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
Desktop with chat:
|
||||
┌──────────────────────┬──────────┐
|
||||
│ │ │
|
||||
│ Video (16:9) │ Chat │
|
||||
│ │ (300px) │
|
||||
│ │ │
|
||||
└──────────────────────┴──────────┘
|
||||
|
||||
Mobile (video only, full width):
|
||||
┌──────────────────────────────────┐
|
||||
│ │
|
||||
│ Video (16:9) │
|
||||
│ │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Performance Notes
|
||||
|
||||
- Use lazy loading: only load iframe when expanded
|
||||
- Consider max 3 simultaneous embeds (optional limit)
|
||||
- iframes are heavy - show placeholder/thumbnail when collapsed
|
||||
|
||||
## References
|
||||
|
||||
- Twitch embed docs: https://dev.twitch.tv/docs/embed/video-and-clips/
|
||||
- Chat embed docs: https://dev.twitch.tv/docs/embed/chat/
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
# sendou.ink-rbyg
|
||||
title: Mutual friends display
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:32:58Z
|
||||
updated_at: 2026-01-13T09:32:58Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Show mutual friends on user profile pages.
|
||||
|
||||
## Display
|
||||
|
||||
On profile page, show:
|
||||
- "X mutual friends" count
|
||||
- Preview of 3-5 mutual friend avatars
|
||||
- Click to expand/see full list
|
||||
|
||||
## Implementation
|
||||
|
||||
- `FriendRepository.findMutualFriends(viewerId, profileUserId)`
|
||||
- Returns users who are friends with both
|
||||
- Count and limited preview in loader
|
||||
- Full list modal or expandable section
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Add mutual friends query to repository
|
||||
- [ ] Add to profile page loader
|
||||
- [ ] Mutual friends preview component
|
||||
- [ ] Full list modal/expansion
|
||||
- [ ] Handle zero mutual friends
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
# sendou.ink-reks
|
||||
title: Define sidebar loading behavior
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T09:27:48Z
|
||||
updated_at: 2026-01-25T12:08:55Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
Currently the sidebar shows empty/nothing while data loads, making the page appear broken briefly.
|
||||
|
||||
## Task
|
||||
|
||||
Define how the sidebar should behave when loading data:
|
||||
- Should we show skeleton loaders?
|
||||
- Should we show the previous cached data while fetching fresh data?
|
||||
- Should we show a loading spinner?
|
||||
- What about error states if the fetch fails?
|
||||
|
||||
## Current Implementation
|
||||
|
||||
- Sidebar uses a fetcher to load data on mount (`app/components/layout/index.tsx`)
|
||||
- No loading or error states are shown
|
||||
- If fetcher fails, error is silently ignored
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
---
|
||||
# sendou.ink-s23a
|
||||
title: Implement hover menu switching
|
||||
status: draft
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:55Z
|
||||
updated_at: 2026-01-11T19:06:55Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
After clicking to open a menu, moving cursor to another menu item should show that menu's items. Menu should close on outside click or Escape key. Location: app/components/layout/TopNavMenus.tsx:14
|
||||
|
||||
## Blocked
|
||||
|
||||
React Aria Components doesn't make this easy currently. See: https://github.com/adobe/react-spectrum/issues/8905
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
---
|
||||
# sendou.ink-s83f
|
||||
title: Restore Sendou blue+pink and white+pink themes
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T09:49:34Z
|
||||
updated_at: 2026-01-11T09:49:34Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Re-add the classic Sendou themes for the CSS rework:
|
||||
|
||||
1. **Blue + Pink** - The signature Sendou.ink dark theme
|
||||
2. **White + Pink** - Light theme variant
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Define theme CSS variables for blue+pink theme
|
||||
- [ ] Define theme CSS variables for white+pink theme
|
||||
- [ ] Verify accessibility/contrast requirements are met
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
# sendou.ink-sb5p
|
||||
title: Create recent vods preview component
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:22:34Z
|
||||
updated_at: 2026-01-11T12:22:34Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create a React component that displays 5 recent VODs for a weapon.
|
||||
|
||||
## Features
|
||||
|
||||
- Show 5 most recent VODs featuring the weapon
|
||||
- Each VOD shows: thumbnail, title, date, player(s)
|
||||
- "View all" link to `/vods?weapon={weaponId}`
|
||||
|
||||
## Data Source
|
||||
|
||||
- `VodRepository.findVods()` with weapon filter
|
||||
- Includes alt skins/kits via `weaponIdToArrayWithAlts()`
|
||||
|
||||
## Props
|
||||
|
||||
- `vods` - array of 5 vod objects
|
||||
- `weaponId` - for "view all" link
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Reuse existing VOD display components if available (`VodListing`)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-sonu
|
||||
title: E2E test desktop sidenav
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:28:33Z
|
||||
updated_at: 2026-01-11T12:28:33Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Write Playwright E2E tests for the desktop sidenav functionality including navigation, collapsing, and user interactions.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
# sendou.ink-svz2
|
||||
title: Inline function in NotificationPopover
|
||||
status: completed
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:55Z
|
||||
updated_at: 2026-01-11T12:41:51Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Refactor NotificationPopover by inlining the separate function that makes no sense as standalone. Location: app/components/layout/NotificationPopover.tsx:40
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
# sendou.ink-takt
|
||||
title: Mobile menu doesn't block background scrolling
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-11T18:39:55Z
|
||||
updated_at: 2026-01-11T18:39:55Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
The mobile menu doesn't actually block scrolling the container when open. This might be a bug with our react-aria components scroll lock workaround.
|
||||
|
||||
## Context
|
||||
- Mobile menu should prevent background content from scrolling when open
|
||||
- Current react-aria scroll lock implementation may not be working correctly
|
||||
|
||||
## Investigation needed
|
||||
- Check the current scroll lock workaround implementation
|
||||
- Verify if this is a react-aria issue or our custom code
|
||||
- Test on different mobile browsers
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
---
|
||||
# sendou.ink-tnjk
|
||||
title: Rewrite weapon page UI
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:23:05Z
|
||||
updated_at: 2026-01-11T12:23:05Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Replace the existing placeholder weapon page with the new design using all created components.
|
||||
|
||||
## Components to Integrate
|
||||
|
||||
- Weapon header (image, name)
|
||||
- Stats summary (top XP holder, popularity)
|
||||
- Quick links
|
||||
- Parameter comparison table
|
||||
- Recent vods preview (5)
|
||||
- Popular builds preview (5)
|
||||
- Art preview (5)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Replace existing `/app/features/weapons/routes/weapons.$slug.tsx`
|
||||
- Well-componentized - each section in its own component for easy reordering
|
||||
- Use CSS modules for styling
|
||||
- Responsive design (desktop + mobile)
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Import data from rewritten loader
|
||||
- Each section component receives props from loader data
|
||||
- Handle empty states gracefully (e.g., "No art tagged for this weapon yet")
|
||||
- Order of sections can be adjusted later - keep components decoupled
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
# sendou.ink-tq5i
|
||||
title: Fix bracket lines and match timer color contrast
|
||||
status: todo
|
||||
type: bug
|
||||
created_at: 2026-01-11T09:36:11Z
|
||||
updated_at: 2026-01-11T09:36:11Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Problem
|
||||
|
||||
On the tournament bracket page, the bracket connector lines and match timer badge blend together because they use the same or very similar colors. This makes it difficult to visually distinguish the timer from the bracket structure.
|
||||
|
||||
## Screenshot
|
||||
|
||||
The timer showing "0m" and the bracket lines are both a similar gray/muted color, reducing visual clarity.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The bracket lines and match timer should have distinct colors so they're easily distinguishable at a glance.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- Bracket connector lines and match timer have sufficient color contrast between them
|
||||
- Both elements remain accessible and readable
|
||||
- Fits within the new CSS variable system in `vars.css`
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
# sendou.ink-u4ag
|
||||
title: My events future work
|
||||
status: draft
|
||||
type: epic
|
||||
created_at: 2026-01-11T12:55:35Z
|
||||
updated_at: 2026-01-11T12:55:35Z
|
||||
---
|
||||
|
||||
Future enhancements for the My Events page after initial implementation is complete.
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
# sendou.ink-u6b2
|
||||
title: Deprecate /to/:id/streams with redirect
|
||||
status: todo
|
||||
type: task
|
||||
priority: normal
|
||||
created_at: 2026-01-12T09:20:46Z
|
||||
updated_at: 2026-01-12T12:07:11Z
|
||||
parent: sendou.ink-r6ry
|
||||
---
|
||||
|
||||
Remove the old tournament streams page and redirect to unified /streams page.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Redirect /to/:id/streams to /streams?tournament=:id (or similar filter)
|
||||
- Tournament bracket LIVE popovers retain current behavior (no change)
|
||||
- Keep redirect permanent (301)
|
||||
|
||||
## Files to Update
|
||||
|
||||
- /app/features/tournament/routes/to.$id.streams.tsx - convert to redirect
|
||||
- routes.ts - may need route changes
|
||||
|
||||
## Notes
|
||||
|
||||
- Should be done in same release as /streams page launch
|
||||
- Preserve any bookmarked URLs via redirect
|
||||
- Bracket popover behavior is separate and unchanged
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
# sendou.ink-utog
|
||||
title: Update user-pickable themes to use new CSS vars
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T09:49:34Z
|
||||
updated_at: 2026-01-11T09:49:34Z
|
||||
parent: sendou.ink-1l22
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
User profile pages and team pages allow custom theme colors. These need to be updated to work with the new CSS variable system from the CSS rework.
|
||||
|
||||
## Affected areas
|
||||
|
||||
- **User pages** - Profile customization with user-selected colors
|
||||
- **Team pages** - Team branding colors
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Audit current user theme implementation
|
||||
- [ ] Map old theme values to new CSS variable system
|
||||
- [ ] Update user page theme application logic
|
||||
- [ ] Update team page theme application logic
|
||||
- [ ] Test custom themes don't break with new CSS structure
|
||||
- [ ] Ensure theme picker UI works correctly
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
---
|
||||
# sendou.ink-uvge
|
||||
title: Create weapon quick links component
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:22:54Z
|
||||
updated_at: 2026-01-11T12:22:54Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Create a React component that displays quick links to related pages.
|
||||
|
||||
## Links to Include
|
||||
|
||||
- **Builds** - `/builds/{weaponSlug}`
|
||||
- **Popular Builds** - `/builds/{weaponSlug}/popular`
|
||||
- **Ability Stats** - `/builds/{weaponSlug}/stats`
|
||||
- **VODs** - `/vods?weapon={weaponId}`
|
||||
- **Build Analyzer** - `/analyzer` (with weapon pre-selected if possible)
|
||||
- **Object Damage Calculator** - `/object-damage-calculator`
|
||||
- **Free Agents** - Link to SendouQ looking page filtered by weapon
|
||||
- **Leaderboard** - `/leaderboards?type=XP-WEAPON-{weaponId}` (shown with top XP holder)
|
||||
|
||||
## Props
|
||||
|
||||
- `weaponSlug`
|
||||
- `weaponId`
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Use existing `LinkButton` component
|
||||
- Appropriate icons for each link (existing icons in codebase)
|
||||
- Some links may be grouped with related features (e.g., leaderboard with stats summary)
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
# sendou.ink-v42i
|
||||
title: Check brackets UI design
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:34:21Z
|
||||
updated_at: 2026-01-11T12:34:21Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
Review the brackets UI and decide on design questions:
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Should tabs (Main/Underground) be "attached" to brackets outline?
|
||||
- [ ] Should "Add sub" link to a different page?
|
||||
- [ ] Compactify button restyle needed?
|
||||
- [ ] Do we need "Go to match" button when match info is already in the sidebar?
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
---
|
||||
# sendou.ink-vbbi
|
||||
title: Rewrite weapon page loader
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T12:22:54Z
|
||||
updated_at: 2026-01-11T12:22:54Z
|
||||
parent: sendou.ink-0ze4
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Rewrite the loader for `/weapons/:slug` to fetch all data needed for the new weapon page.
|
||||
|
||||
## Data to Fetch
|
||||
|
||||
All in a single loader:
|
||||
|
||||
1. **Weapon info** - ID, name, slug, category (existing)
|
||||
2. **Weapon params** - From JSON files, including patch history
|
||||
3. **Category weapons** - All weapons in same category for comparison table
|
||||
4. **Top XP holder** - From `weaponXPLeaderboard(weaponId)`
|
||||
5. **Popularity stats** - Overall rank + category rank from XRankPlacement
|
||||
6. **Recent vods** - 5 most recent from `VodRepository.findVods()`
|
||||
7. **Popular builds** - 5 most popular from BuildRepository
|
||||
8. **Art by tag** - 5 art pieces tagged with weapon slug
|
||||
|
||||
## Location
|
||||
|
||||
`/app/features/weapons/loaders/weapons.$slug.server.ts`
|
||||
|
||||
## Technical Notes
|
||||
|
||||
- Use Promise.all for parallel DB queries where possible
|
||||
- Consider caching for expensive queries
|
||||
- Handle missing data gracefully (e.g., no art tagged yet)
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
---
|
||||
# sendou.ink-vd9w
|
||||
title: Migration from trust to friendship
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-13T09:33:20Z
|
||||
updated_at: 2026-01-13T09:33:20Z
|
||||
parent: sendou.ink-255r
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Migrate existing TrustRelationship data to new Friendship system.
|
||||
|
||||
## Migration Logic
|
||||
|
||||
```sql
|
||||
-- Find mutual trusts (A trusts B AND B trusts A)
|
||||
-- Convert to friendships
|
||||
|
||||
INSERT INTO Friendship (userOneId, userTwoId, createdAt)
|
||||
SELECT
|
||||
CASE WHEN t1.trustGiverUserId < t1.trustReceiverUserId
|
||||
THEN t1.trustGiverUserId
|
||||
ELSE t1.trustReceiverUserId END,
|
||||
CASE WHEN t1.trustGiverUserId < t1.trustReceiverUserId
|
||||
THEN t1.trustReceiverUserId
|
||||
ELSE t1.trustGiverUserId END,
|
||||
MIN(t1.lastUsedAt)
|
||||
FROM TrustRelationship t1
|
||||
JOIN TrustRelationship t2
|
||||
ON t1.trustGiverUserId = t2.trustReceiverUserId
|
||||
AND t1.trustReceiverUserId = t2.trustGiverUserId
|
||||
WHERE t1.trustGiverUserId < t1.trustReceiverUserId
|
||||
GROUP BY 1, 2;
|
||||
|
||||
-- Delete all trust relationships (mutual converted, one-way discarded)
|
||||
DELETE FROM TrustRelationship;
|
||||
```
|
||||
|
||||
## Approach
|
||||
|
||||
1. Create migration script (not DB migration - one-time data migration)
|
||||
2. Run on staging first
|
||||
3. Verify friendship counts match expected
|
||||
4. Run on production
|
||||
5. Keep TrustRelationship table temporarily for rollback
|
||||
6. Remove table in later migration after confirming stability
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Create migration script
|
||||
- [ ] Test on development database
|
||||
- [ ] Count mutual trusts before migration
|
||||
- [ ] Verify friendship count after migration
|
||||
- [ ] Test on staging
|
||||
- [ ] Run on production
|
||||
- [ ] Monitor for issues
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
# sendou.ink-vj1n
|
||||
title: Fix organizations icon in CommandPalette
|
||||
status: completed
|
||||
type: bug
|
||||
priority: normal
|
||||
created_at: 2026-01-11T08:58:55Z
|
||||
updated_at: 2026-01-11T13:17:39Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
The organizations category uses wrong icon. Should use the same icon as AnythingAdder uses for organizations. Location: app/components/layout/CommandPalette.tsx:42
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
# sendou.ink-vmid
|
||||
title: Define navigation menu categories
|
||||
status: todo
|
||||
type: task
|
||||
created_at: 2026-01-11T08:58:54Z
|
||||
updated_at: 2026-01-11T08:58:54Z
|
||||
parent: sendou.ink-6eko
|
||||
---
|
||||
|
||||
Replace placeholder categories in TopNavMenus with actual navigation structure. Location: app/components/layout/TopNavMenus.tsx:13
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user