Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ This is a non-negotiable security requirement.
- **Hypothesize and Verify:** Treat fixes as hypotheses and verify them with tests.
- **Consult Docs Before Guessing:** When an error occurs, consult official documentation first.
- **Keep Architecture Document Updated:** After implementing a new feature, update `docs/ARCHITECTURE.md` to reflect the changes.
- **Do Not Start Servers:** Never start servers, whether through `docker compose up` or `iex -S mix phx.server`.

### Iterative Refinement
- When we are working on a document or a piece of code, do not reprint the entire file after every change. Acknowledge that you have understood the change, and wait for me to ask before you display the full content.
Expand Down Expand Up @@ -75,4 +76,4 @@ This is a non-negotiable security requirement.
- **Debug the App, Not the Test:** Analyze the stack trace to find the root cause in the application code.
- **Testing LiveView Navigation:** Use the `follow_redirect(conn)` helper to test `push_navigate` or `push_redirect`.
- **Testing Stateless Components:** Use `render_component/2` for stateless functional components.
- **Testing with Scope:** Use the `log_in_user/2` helper in tests to set up the `current_scope`.
- **Testing with Scope:** Use the `log_in_user/2` helper in tests to set up the `current_scope`.
16 changes: 16 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,22 @@

/* This file is for your main application CSS */

@utility z-base {
z-index: 10;
}
@utility z-popover {
z-index: 20;
}
@utility z-sticky {
z-index: 30;
}
@utility z-drawer {
z-index: 40;
}
@utility z-modal {
z-index: 50;
}

@utility main-margins {
@apply max-w-2xl mx-auto;
}
20 changes: 20 additions & 0 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,23 @@ The business logic in `lib/cms` is organized into "contexts." Each context is a
* **Purpose:** Manages the church's library of worship songs.
* **Associated Schemas:**
* `CMS.Songs.Song`: Represents a single song, including its title, lyrics, author, and other metadata.

## Frontend Conventions

### Z-Index Scale

To ensure a consistent and predictable stacking order for UI elements, we use a semantic z-index scale. Instead of using arbitrary numeric values, you **must** use the following Tailwind CSS utility classes:

* `z-base`: For elements that need a base stacking context. (z-index: 10)
* `z-popover`: For popovers and dropdowns. (z-index: 20)
* `z-sticky`: For sticky elements like navbars. (z-index: 30)
* `z-drawer`: For drawers and sidebars. (z-index: 40)
* `z-modal`: For modals and overlays that must appear on top of all other content. (z-index: 50)

**Example:**

```html
<div class="modal z-modal">
<!-- Modal content -->
</div>
```
58 changes: 58 additions & 0 deletions docs/sub_issue_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Sub-Issue Template (Vertical Slice)

Each sub-issue you create **must** follow this format. This template is designed to describe a "vertical slice" of functionality, from the user interface down to the database.

---

**Title:** A clear, user-centric summary of the feature slice.
* *Example:* "User can submit the new prayer request form and see a success message."

**Goal:** Briefly explain the "why" of this specific task and what new capability it delivers to the user.
* *Example:* "This task connects the UI form to the backend, allowing users to save their prayer requests for the first time. It provides the core 'happy path' functionality."

**Affected Components:** List the primary files/modules involved in this slice.
* *Example:*
* **LiveView:** `lib/cms_web/live/prayer_request_live/new.ex`
* **Context:** `lib/cms/prayers.ex`
* **Schema:** `lib/cms/prayers/prayer_request.ex`

**Implementation Steps:** Describe the sequence of changes needed to implement the slice.
* *Example:*
1. In `prayers.ex`, create a new function `create_prayer_request(attrs)` that takes valid attributes and saves a new `PrayerRequest` to the database.
2. In the `new.ex` LiveView, implement a `handle_event` for the "save" event from the form.
3. This event handler should call the new `create_prayer_request` context function.
4. On successful creation, redirect the user to the prayer request index page and display a "Prayer Request created!" flash message.

**How to Verify:** Provide simple, end-to-end steps to confirm the slice is working correctly.
* *Example:*
1. Navigate to the `/prayer-requests/new` page.
2. Fill out the form fields and click "Save".
3. Confirm that the page redirects to the index page.
4. Confirm that a success message is displayed.
5. (Optional) Check the database to ensure the new record was saved correctly.

**BDD Scenario:** This scenario describes the required user-facing behavior. It is written in Gherkin syntax for clarity and communication, not because the project uses a Gherkin-based tool. The developer should implement this scenario as a standard feature test using the project's existing testing framework (e.g., ExUnit).
* *Example:*
```gherkin
Scenario: User successfully submits a new prayer request
Given I am on the new prayer request page
When I fill in "Title" with "Healing for Sarah"
And I fill in "Details" with "Please pray for my friend Sarah's recovery."
And I click the "Save" button
Then I should be on the prayer requests page
And I should see a flash message saying "Prayer Request created!"
```

**Unit Tests:** In addition to the BDD scenario, add lower-level tests for the core business logic to ensure correctness and enable faster debugging.
* *Example:*
* **File:** `test/cms/prayers_test.exs`
* **Function:** `create_prayer_request/1`
* **Scenarios to test:**
* Returns `{:ok, %PrayerRequest{}}` with valid attributes.
* Returns `{:error, %Ecto.Changeset{}}` when the title is missing.
* Correctly sets the `organization_id` on the new prayer request.

**Definition of Done:**
* All implementation steps are complete.
* All verification steps pass.
* The changes are committed with a clear and descriptive message that closes this issue (e.g., `Closes #<issue_number>`).
2 changes: 1 addition & 1 deletion lib/cms_web/components/bottom_dock.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule CMSWeb.BottomDock do

def bottom_dock(assigns) do
~H"""
<div class="dock dock-center sm:hidden z-40 print:hidden">
<div class="dock dock-center sm:hidden z-drawer print:hidden">
<.link navigate={~p"/liturgies/latest"} class="dock-item">
<.icon name="hero-book-open-solid" class="w-5 h-5" />
<span class="dock-label">{gettext("Liturgy")}</span>
Expand Down
2 changes: 1 addition & 1 deletion lib/cms_web/components/core_components.ex
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ defmodule CMSWeb.CoreComponents do
phx-hook="Flash"
data-timeout={@timeout}
role="alert"
class="toast toast-bottom toast-center z-50"
class="toast toast-bottom toast-center z-modal"
{@rest}
>
<div class={[
Expand Down
6 changes: 3 additions & 3 deletions lib/cms_web/components/main_layout.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ defmodule CMSWeb.MainLayout do
<.drawer show={false} />
<.bottom_dock current_scope={@current_scope} />
</div>
<div id="sidebar-container" class="drawer-side z-80" phx-hook="Sidebar">
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this was previously at z-80, why did you use z-drawer, rather than z-modal?

<div id="sidebar-container" class="drawer-side z-modal" phx-hook="Sidebar">
<label for="sidebar-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
<.sidebar qr_code_svg={@qr_code_svg}>
<:sidebar_top>
Expand All @@ -69,7 +69,7 @@ defmodule CMSWeb.MainLayout do
~H"""
<div
id="pwa-install-banner"
class="fixed bottom-0 left-0 w-full bg-neutral text-neutral-content p-4 text-center z-[1000] hidden"
class="fixed bottom-0 left-0 w-full bg-neutral text-neutral-content p-4 text-center z-modal hidden"
phx-update="ignore"
>
<p class="mb-2">{gettext("Deseja instalar esta aplicação no seu dispositivo?")}</p>
Expand All @@ -87,7 +87,7 @@ defmodule CMSWeb.MainLayout do
~H"""
<div
id="pwa-ios-install-banner"
class="fixed bottom-0 left-0 w-full bg-neutral text-neutral-content p-4 text-center z-[1000] hidden"
class="fixed bottom-0 left-0 w-full bg-neutral text-neutral-content p-4 text-center z-modal hidden"
phx-update="ignore"
>
<p class="mb-2">
Expand Down
8 changes: 4 additions & 4 deletions lib/cms_web/components/navbar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ defmodule CMSWeb.Navbar do

def navbar(assigns) do
~H"""
<div class="sticky top-0 z-80 px-2 flex items-center flex-shrink-0 bg-base-100 shadow-md print:shadow-none">
<div class="sticky top-0 z-sticky px-2 flex items-center flex-shrink-0 bg-base-100 shadow-md print:shadow-none">
<.hamburger_button :if={@show_sidebar_button} />
<div class="navbar z-50 print:main-margins print:px-6">
<div class="navbar z-sticky print:main-margins print:px-6">
<div class="navbar-start">
<span class="font-medium">{@page_title}</span>
</div>
Expand All @@ -57,7 +57,7 @@ defmodule CMSWeb.Navbar do

def hamburger_button(assigns) do
~H"""
<label for="sidebar-drawer" class="btn btn-ghost mx-1 px-2 z-100 print:hidden">
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as above.

<label for="sidebar-drawer" class="btn btn-ghost mx-1 px-2 z-modal print:hidden">
<.icon name="hero-bars-3" class="h-5 w-5" />
</label>
"""
Expand All @@ -78,7 +78,7 @@ defmodule CMSWeb.Navbar do
</div>
<ul
tabindex="0"
class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52 mt-4 z-[1]"
class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52 mt-4 z-popover"
>
<li :if={@current_scope.user.role == :admin}>
<.link href={~p"/admin/users"}>{gettext("Utilizadores")}</.link>
Expand Down
2 changes: 1 addition & 1 deletion lib/cms_web/components/settings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule CMSWeb.Settings do
~H"""
<div
id="settings-drawer"
class={"print:hidden fixed bottom-0 left-0 right-0 bg-base-200 p-4 pb-20 transform transition-transform duration-300 ease-in-out z-30" <> if(@show, do: " translate-y-0", else: " translate-y-full")}
class={"print:hidden fixed bottom-0 left-0 right-0 bg-base-200 p-4 pb-20 transform transition-transform duration-300 ease-in-out z-sticky" <> if(@show, do: " translate-y-0", else: " translate-y-full")}
>
<div class="flex justify-between items-center">
<p>Definições</p>
Expand Down
31 changes: 31 additions & 0 deletions prompts/developer_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Junior Developer Workflow: Implementing an Issue

Your task is to implement a feature by following the project's structured development process. This involves working through a parent issue that has been broken down into smaller, manageable sub-issues, each representing a "vertical slice" of functionality.

## Your Workflow

1. **Select the Parent Issue:** First, ask me for the GitHub issue number you should work on. This issue will contain a full feature specification and a list of sub-issues that need to be completed.

2. **Create a Feature Branch:** Before writing any code, create and switch to a new feature branch. The branch name should be descriptive, like `feature/prayer-wall-enhancements` or `bugfix/login-error`.

3. **Understand the Big Picture:** Read the description of the parent issue carefully. Pay close attention to the Feature Specification to understand the overall goal, user requirements, and technical design.

4. **Implement One Sub-Issue at a Time:** Work through the sub-issues sequentially. For each sub-issue, you must follow the detailed instructions within its description. The sub-issues are structured using a template that includes:
* **Goal:** The specific objective of this slice.
* **Affected Components:** The files you will likely need to modify.
* **Implementation Steps:** The code changes you need to make.
* **How to Verify:** Manual steps to confirm the slice is working.
* **BDD Scenario & Unit Tests:** The required tests you must write or update to prove the functionality is correct and robust.

5. **Develop and Test:**
* Implement the code changes as described in the **Implementation Steps**.
* Write and pass the tests described in the **BDD Scenario** and **Unit Tests** sections. Use the project's existing testing framework (`mix test`).
* Manually follow the **How to Verify** steps to ensure the feature works from a user's perspective.

6. **Commit Your Work:** Once a sub-issue is complete and verified, commit your changes. Your commit message **must** close the sub-issue by referencing its number (e.g., `Closes #123`).

7. **Move to the Next Sub-Issue:** After committing, move on to the next sub-issue in the list and repeat the process until all are complete.

8. **Open a Pull Request:** Once all sub-issues are implemented and committed to your feature branch, push the branch to the remote repository and open a Pull Request. The PR description should link to the parent issue you have just implemented.

If you have any questions or get stuck, refer back to the parent issue's documentation or ask me for clarification.
23 changes: 23 additions & 0 deletions prompts/issue_decomposition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Prompt: GitHub Issue Decomposition (BDD Style)

Your task is to act as an expert senior developer and guide me through a collaborative and iterative process of breaking down a GitHub issue. We will use a Behavior-Driven Development (BDD) approach to create a series of high-level, incremental sub-issues. The goal is to produce tasks so clear and self-contained that they can be easily implemented by a **junior developer** and reviewed by a stakeholder.

---
### Our Workflow
- This document is a living template. As we refine it, please only confirm the changes you've made. Do not reprint the entire document unless I ask for it.
---

### Process

1. **Identify the Target Issue:**
* Start by asking the user to provide the URL of the GitHub issue you need to decompose. Once you have the issue, proceed to the next step.

2. **Full Context Analysis:**
* Thoroughly read the provided GitHub issue to understand the user's goal, the problem to be solved, and any acceptance criteria mentioned.
* Investigate the codebase to gather technical context. Use `search_file_content`, `glob`, and `read_file` to find relevant files, modules, and functions.
* Consult `GEMINI.md`, `README.md`, and any documents in `docs/` to understand the project's architecture, conventions, and required commands.

3. **Decomposition and Creation:**
* Plan a logical sequence of steps that deliver value incrementally. Focus on creating "vertical slices" of functionality. For example, when creating a new form, a good sequence is: 1. Build the basic UI. 2. Implement the logic to save the data to the database. 3. Add validations and display user feedback.
* Each sub-issue must represent a distinct, verifiable step in this sequence.
* For each step, you will first **create a new issue** using the template in `docs/sub_issue_template.md`. Immediately after the issue is created, you will **link it as a sub-issue** to the parent.
37 changes: 37 additions & 0 deletions prompts/logical_commit_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Prompt: Committing Uncommitted Changes with Logical Separation

Your task is to analyze all uncommitted changes in the repository and commit them in a series of distinct, logical units. Each commit must represent a single, cohesive change. You must follow this process rigorously to ensure accuracy and avoid incorrect assumptions.

---
### Core Principles

1. **No Assumptions, Ever:** Do not assume files are related based on their location (e.g., being in the same directory), their file names, or the fact that they were changed around the same time. Grouping files is a conclusion, not a starting point.
2. **Verify, Then Act:** The only way to be certain that files are related is to examine their content. You must read the files and understand their purpose before proposing to group them in a commit.
3. **One Logical Change Per Commit:** Each commit should be atomic. A reviewer should be able to understand the entire change by reading the commit message and looking at the diff. If a change involves both a bug fix and a new feature, they must be in separate commits.

---
### Step-by-Step Workflow

1. **Initial Analysis:**
* Run `git status --porcelain && git diff HEAD` to get a complete and concise overview of all modified, staged, and untracked files.

2. **Identify and Handle Self-Contained Changes:**
* From the initial analysis, identify the simplest, most obvious changes first. A modification to a single documentation file, for example, is a good candidate.
* If you find a self-contained change, stage only that file, write a clear commit message, and commit it.

3. **Process Remaining and Untracked Files (The Verification Loop):**
* For all remaining modified or untracked files, list them for the user.
* **Crucially, you must not propose grouping them yet.**
* Before proposing any action, you must investigate the content:
* For **modified files**, use `git diff <file_path>` to analyze the specific changes.
* For **new, untracked files**, use `read_file <file_path>` to understand their full purpose.
* After your investigation, present your analysis. State clearly **why** you believe a set of files belongs together in a single commit, basing your reasoning *only* on their content. For example: "The changes in `a.js` and `b.js` both contribute to the new caching feature. The new file `c.js` provides the core utility for this cache."
* Propose to stage *only* that specific, verified logical group.
* Once the proposal is accepted, stage the files and write a comprehensive commit message that explains the purpose of the change.

4. **Iterate:**
* Repeat Step 3 for any remaining files. Continue the "Read -> Analyze -> Propose -> Commit" loop until the working directory is clean.

5. **Final Confirmation:**
* Run `git status` one last time to confirm that the working directory is clean and all changes have been committed.
* Inform the user that the process is complete.
Loading