Learning goals in Sunschool are reward-based incentives created by parents to motivate learners. Goals encourage sustained engagement by letting learners save points toward tangible rewards.
Goals are different from achievements. Achievements are earned automatically for milestones. Goals are parent-defined rewards that learners save points toward.
Status: PENDINGLearner sees: ”⏳ Waiting for parent approval…”Goal card shows: “Waiting…” badge in orange
4
Parent Reviews Request
Parent sees notification in their dashboardOptions:
Approve with optional notes
Reject with explanation
5
Approval: Points Reset
If approved:
Saved points for that goal reset to 0
Learner can earn the same reward again
Parent delivers the actual reward
Copy
Ask AI
// From rewards-service.ts:460-465// Deduct saved_points (reset to 0 so they can earn again)await client.query( `UPDATE reward_goal_savings SET saved_points=0, updated_at=NOW() WHERE learner_id=$1 AND reward_id=$2`, [r.learner_id, r.reward_id]);
// From rewards-service.ts:467-476// Auto-deactivate if max redemptions reachedconst ur = updatedReward[0];if (ur?.max_redemptions && ur.current_redemptions >= ur.max_redemptions) { await client.query( `UPDATE rewards SET is_active = FALSE, updated_at=NOW() WHERE id=$1`, [r.reward_id] ); // Refund any other learners' savings for this now-deactivated reward await refundSavingsForReward(client, r.reward_id);}
Repeatable System:
After approval, saved points reset to 0
Goal remains active (unless max redemptions reached)
Learner can start saving again immediately
Parents can set maxRedemptions to limit times earned
If parents delete or deactivate a goal, saved points are refunded:
Copy
Ask AI
// From rewards-service.ts:68-101async function refundSavingsForReward(client: any, rewardId: string) { const { rows: savings } = await client.query( `SELECT learner_id, saved_points FROM reward_goal_savings WHERE reward_id = $1 AND saved_points > 0`, [rewardId] ); for (const s of savings) { // Credit points back to learner balance await client.query( `UPDATE learner_points SET current_balance = current_balance + $1, last_updated = NOW() WHERE learner_id = $2`, [s.saved_points, s.learner_id] ); // Record ledger entry for the refund await client.query( `INSERT INTO points_ledger (learner_id, amount, source_type, source_id, description) VALUES ($1, $2, 'GOAL_REFUND', $3, 'Reward removed — saved points refunded')`, [s.learner_id, s.saved_points, rewardId] ); // Zero out the savings await client.query( `UPDATE reward_goal_savings SET saved_points = 0, updated_at = NOW() WHERE learner_id = $1 AND reward_id = $2`, [s.learner_id, rewardId] ); } return savings.length;}
Refund Policy: When goals are deleted or deactivated, all saved points are automatically returned to learners’ general balances with a ledger entry for transparency.
// From learner-goals-page.tsx:272-278{goals.length === 0 ? ( <View style={styles.empty}> <Text style={{ fontSize: 52 }}>🎁</Text> <Text style={styles.emptyTitle}>No goals yet!</Text> <Text style={styles.emptyDesc}> Ask your parent to add some rewards for you to earn. </Text> </View>
Encourages learners to communicate with parents about desired rewards.