7.0 KiB
The idea behind this application is to be able to keep track of scores within Dynamics. A Dynamic is usually between two people, but it might be between multiple people. I don't think it currently makes sense to have a Dynamic for a single person, but there should not be a hard requirement for it to be that way. Users can have multiple Dynamics, even with the same people.
A Dynamic has scores (Ledgers?). In the definition of a score, some people have the power to add items that mutate the score. Others can add suggestions, which aren't automatically accepted, but instead are awaiting approval. These "Mutations" can have text or media attached to them. A Mutation also has a "chat stream" where it can be discussed, like a forum post. It should have an activity log, containing the chat stream, but also when it was created and when it was approved or denied.
A score (Ledger) also needs to have rules accompanied by it. These rules should just be a text field at first. These rules should not be editable by everybody.
Dynamics have a rules-segment too. Not all people within a dynamic can edit these. Dynamics have an activity log too, with a forum-post-like chat.
The interface should be in Vue, nicely structured into components and pages. Esthetic is BDSM centered, but clean. Start with dark mode, light mode (camouflaged as a more innocent, corporate esthetical theme) might be a good feature in the future.
Make use of inertia, laravel reverb for notifications, pest for tests. Make git commits for features.
Session Developments & Achievements
During this session, we successfully built out and verified several core architectural features of the Ledgerrz application:
-
BEM Styling Refactoring (BDSM Theme first):
- Replaced inline Tailwind classes across all core Vue pages and layout components (
Dynamics/Index.vue,Dynamics/Create.vue,Dynamics/Show.vue,Ledgers/Show.vue,ParticipantsList.vue,LedgerList.vue,CreateLedgerForm.vue,AddMutationForm.vue, andMutationList.vue) with structured BEM scoped CSS blocks. - Utilized Tailwind v4
@applyand@referenceinside<style scoped>blocks to prevent code duplication, enforce a dark-first BDSM aesthetic, and maintain clear separation of concerns.
- Replaced inline Tailwind classes across all core Vue pages and layout components (
-
Ledger Alignment & Scoring Logic:
- Added an
alignmentcolumn (positive,neutral,negative) to Ledgers, affecting the color coding of mutations:- Positive Alignment: higher score is better; additions are green (+), demerits/deductions are red (-).
- Negative Alignment: lower score is better (demerits); deductions are green (-) as they reduce demerits, and additions/infractions are red (+) as they increase demerits.
- Neutral Alignment: standard scoring, styled in gray/neutral colors.
- Added an "Alignment" dropdown selector in the ledger creation form.
- Added an
-
Demerit Authorship Correction:
- Corrected database seeders so demerits/penalty mutations are authored by the Dominant/Owner user (
aliceortestUser) rather than the submissive (bob), aligning with realistic power exchange dynamics.
- Corrected database seeders so demerits/penalty mutations are authored by the Dominant/Owner user (
-
Read Cursor & Dashboard Activities Highlights:
- Designed and built a polymorphic
read_cursorstable to track a user's last-viewed timestamp on individual Dynamics and Ledgers. - Developed
ActivityServiceto chronological sort and partition dynamic activity (messages, ledger creation) and ledger activity (mutations, approval updates, and comments) into unread vs. read categories. - Highlighted unread entities grouped together on the user's dashboard, displaying the last two already-read items as muted context followed by highlighted unread activities with a prominent
NEWbadge. - Visiting a Dynamic/Ledger automatically updates its read cursor, removing it from subsequent dashboard loads.
- Dynamically shared the unread entity count as a global Inertia prop, rendering a vibrant red dot notification badge over a bell icon in the top-right of the header.
- Designed and built a polymorphic
-
Broadcasts, Environment & Verification:
- Configured real-time notifications utilizing Laravel Reverb.
- Documented CLI environment test pollution learnings inside
AGENTS.mdto prevent future CSRF419errors. - Ensured full production assets compilation (
npm run build) and achieved 45/45 passing Pest PHP tests with 206 assertions.
-
Ledger-Scoped Predefined Mutation Templates ("Rewards"):
- Associated reusable point-based predefined mutation templates under specific Ledgers rather than broad Dynamics, mapping perfectly to the mental model of spending points on a ledger.
- Designed them purely as "Rewards" with positive or negative point amounts (handling both demerit-purchases and chores), removing the obsolete
typecategorization for a simpler, type-less, and sleeker UI/UX.
-
User Activity Profiling & Detail Pages:
- Created a dynamic user detail page (
dynamics.users.show) scoped to each dynamic. It displays a participant's role, custom display name, fallback real name, and a clean chronological listing of their 10 most recent mutations (activities) in that dynamic.
- Created a dynamic user detail page (
-
Polymorphic System Message placeholders & Dynamic Client-Side Linking:
- Refactored system log activity messages to use native
<user:userId>placeholders and associated them with polymorphicsubject_idandsubject_typeobjects. - On the client-side, the chat component parses these placeholders into rich, clickable links to User Profiles, and dynamically matches and wraps referenced ledger names into links pointing directly to the ledger show page.
- Added backend-side placeholder resolution inside
ActivityServicefor the dashboard, ensuring unread system logs translate cleanly to real names across multiple dynamics.
- Refactored system log activity messages to use native
-
Vite/Inertia v3 Layout Callback Breadcrumbs:
- Utilized Inertia v3's powerful new layout callback API inside Vue page
defineOptionsto reactively resolve page-specific dynamic breadcrumbs at runtime using parsed page props, making the pages self-contained and keeping PHP controllers beautifully slim.
- Utilized Inertia v3's powerful new layout callback API inside Vue page
-
Silent background Chat Pagination & Smooth Scrolling UX:
- Implemented silent background XHR queries (using native browser
fetch()) on our dedicated message JSON API routes to load older chat pages, completely bypassing browser history/URL pollution and preserving page state on refreshes. - Integrated
preserveScroll: trueinside chat form submissions to completely prevent scroll jumps when sending messages.
- Implemented silent background XHR queries (using native browser
-
Standardized Policy-Driven UI Capabilities:
- Eliminated unstandardized client-side role checks and boolean flags, replacing them with structured
cancapability objects returned directly from Laravel policies. - Combined permission validation with state-based business constraints in
MutationPolicy(e.g., suggestions can be approved/rejected only if'pending'; and voided only if not'voided'), securing both the frontend action buttons and backend controllers simultaneously. - Achieved 65/65 passing Pest PHP tests with 333 assertions.
- Eliminated unstandardized client-side role checks and boolean flags, replacing them with structured