Beads are now a property of prayer steps, not separate steps

Each prayer in the library has an optional default_bead_type (small/large/
crucifix). Standard prayers get sensible defaults: Our Father=large,
Hail Mary=small, Sign of Cross=crucifix, Divine Mercy beads accordingly.

In the sequence, each step card shows a bead selector (—/○/●/✝) so users
can override the default per step. Adding a prayer pre-fills its default.

Bead library icon hints (○●✝) appear on prayer cards in the library.
Modal now includes a Bead selector for creating/editing prayers.

Remove the separate Bead Markers library section — beads live on prayers.
build_slides: prayer steps with bead_type now get a real bead_index so
the ring advances correctly during presentation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-13 22:07:48 -07:00
parent 76a5061fba
commit 8c047f5b28
7 changed files with 228 additions and 159 deletions
+23 -16
View File
@@ -61,7 +61,7 @@ if ($method === 'GET') {
$sql = "
SELECT cp.id, cp.name, cp.leader_text, cp.all_text,
cp.is_global, cp.created_by,
cp.default_bead_type, cp.is_global, cp.created_by,
u.role AS creator_role,
IF(cp.is_global=1 AND u.role='superadmin', 'standard',
IF(cp.is_global=1, 'global', 'mine')) AS source_tag
@@ -83,22 +83,25 @@ if ($method === 'POST') {
$body = json_decode(file_get_contents('php://input'), true);
if (!$body) json_err('Invalid JSON');
$name = trim($body['name'] ?? '');
$leader = trim($body['leader_text'] ?? '');
$all = trim($body['all_text'] ?? '');
$global = $is_admin ? (int)!empty($body['is_global']) : 0;
$name = trim($body['name'] ?? '');
$leader = trim($body['leader_text'] ?? '');
$all = trim($body['all_text'] ?? '');
$global = $is_admin ? (int)!empty($body['is_global']) : 0;
$bead_type = in_array($body['default_bead_type'] ?? '', ['small','large','crucifix'])
? $body['default_bead_type'] : null;
if ($name === '') json_err('Prayer name is required');
$st = $pdo->prepare(
"INSERT INTO custom_prayers (name, leader_text, all_text, is_global, created_by)
VALUES (?, ?, ?, ?, ?)"
"INSERT INTO custom_prayers (name, leader_text, all_text, default_bead_type, is_global, created_by)
VALUES (?, ?, ?, ?, ?, ?)"
);
$st->execute([$name, $leader, $all, $global, $uid]);
$st->execute([$name, $leader, $all, $bead_type, $global, $uid]);
$new_id = (int)$pdo->lastInsertId();
$row = $pdo->prepare("
SELECT cp.id, cp.name, cp.leader_text, cp.all_text, cp.is_global, cp.created_by,
SELECT cp.id, cp.name, cp.leader_text, cp.all_text,
cp.default_bead_type, cp.is_global, cp.created_by,
u.role AS creator_role,
IF(cp.is_global=1 AND u.role='superadmin', 'standard',
IF(cp.is_global=1, 'global', 'mine')) AS source_tag
@@ -126,20 +129,24 @@ if ($method === 'PUT') {
$can_edit = $is_admin || (int)$prayer['created_by'] === $uid;
if (!$can_edit) json_err('Access denied', 403);
$name = trim($body['name'] ?? $prayer['name']);
$leader = trim($body['leader_text'] ?? $prayer['leader_text']);
$all = trim($body['all_text'] ?? $prayer['all_text']);
$global = $is_admin ? (int)!empty($body['is_global']) : (int)$prayer['is_global'];
$name = trim($body['name'] ?? $prayer['name']);
$leader = trim($body['leader_text'] ?? $prayer['leader_text']);
$all = trim($body['all_text'] ?? $prayer['all_text']);
$global = $is_admin ? (int)!empty($body['is_global']) : (int)$prayer['is_global'];
$bead_type = array_key_exists('default_bead_type', $body)
? (in_array($body['default_bead_type'], ['small','large','crucifix']) ? $body['default_bead_type'] : null)
: $prayer['default_bead_type'];
if ($name === '') json_err('Prayer name is required');
$pdo->prepare(
"UPDATE custom_prayers SET name=?, leader_text=?, all_text=?, is_global=?, updated_at=NOW()
"UPDATE custom_prayers SET name=?, leader_text=?, all_text=?, default_bead_type=?, is_global=?, updated_at=NOW()
WHERE id=?"
)->execute([$name, $leader, $all, $global, $id]);
)->execute([$name, $leader, $all, $bead_type, $global, $id]);
$row = $pdo->prepare("
SELECT cp.id, cp.name, cp.leader_text, cp.all_text, cp.is_global, cp.created_by,
SELECT cp.id, cp.name, cp.leader_text, cp.all_text,
cp.default_bead_type, cp.is_global, cp.created_by,
u.role AS creator_role,
IF(cp.is_global=1 AND u.role='superadmin', 'standard',
IF(cp.is_global=1, 'global', 'mine')) AS source_tag