added defaults for now.
reworked tasks and pending rewards
This commit is contained in:
@@ -512,7 +512,7 @@ def reward_status(id):
|
||||
#check to see if this reward id and child id is in the pending rewards db if so set its redeeming flag to true
|
||||
pending_query = Query()
|
||||
pending = pending_reward_db.get((pending_query.child_id == child.id) & (pending_query.reward_id == reward.id))
|
||||
status = RewardStatus(reward.id, reward.name, points_needed, reward.cost, pending, reward.image_id)
|
||||
status = RewardStatus(reward.id, reward.name, points_needed, reward.cost, pending is not None, reward.image_id)
|
||||
statuses.append(status.to_dict())
|
||||
|
||||
statuses.sort(key=lambda s: s['cost'])
|
||||
|
||||
@@ -82,6 +82,42 @@ def populate_default_data():
|
||||
"rewards": rewards
|
||||
}
|
||||
|
||||
def createDefaultTasks():
|
||||
"""Create default tasks if none exist."""
|
||||
if len(task_db.all()) == 0:
|
||||
default_tasks = [
|
||||
Task(name="Take out trash", points=2, is_good=True, image_id="trash-can"),
|
||||
Task(name="Make your bed", points=2, is_good=True, image_id="make-the-bed"),
|
||||
Task(name="Sweep and clean kitchen", points=2, is_good=True, image_id="vacuum"),
|
||||
Task(name="Do homework early", points=2, is_good=True, image_id="homework"),
|
||||
Task(name="Be good for the day", points=2, is_good=True, image_id="good"),
|
||||
Task(name="Clean your mess", points=2, is_good=True, image_id="broom"),
|
||||
|
||||
Task(name="Fighting", points=2, is_good=False, image_id="fighting"),
|
||||
Task(name="Yelling at parents", points=2, is_good=False, image_id="yelling"),
|
||||
Task(name="Lying", points=2, is_good=False, image_id="lying"),
|
||||
Task(name="Not doing what told", points=2, is_good=False, image_id="ignore"),
|
||||
Task(name="Not flushing toilet", points=2, is_good=False, image_id="toilet"),
|
||||
]
|
||||
for task in default_tasks:
|
||||
task_db.insert(task.to_dict())
|
||||
|
||||
def createDefaultRewards():
|
||||
"""Create default rewards if none exist."""
|
||||
if len(reward_db.all()) == 0:
|
||||
default_rewards = [
|
||||
Reward(name="Choose meal", description="Choose dinner or lunch", cost=3, image_id="meal"),
|
||||
Reward(name="$1", description="Money is always nice", cost=8, image_id='money'),
|
||||
Reward(name="$5", description="Even more money", cost=12, image_id='money'),
|
||||
Reward(name="Tablet 1 hour", description="Play your games", cost=5, image_id='tablet'),
|
||||
Reward(name="Computer with dad", description="Let's play a game together", cost=5, image_id='games-with-dad'),
|
||||
Reward(name="Computer 1 hour", description="Minecraft or Terraria?", cost=5, image_id='computer-game'),
|
||||
Reward(name="TV 1 hour", description="Too much is bad for you.", cost=5, image_id='tv'),
|
||||
Reward(name="Candy from store", description="Yum!", cost=5, image_id='candy'),
|
||||
]
|
||||
for reward in default_rewards:
|
||||
reward_db.insert(reward.to_dict())
|
||||
|
||||
def initializeImages():
|
||||
"""Initialize the image database with default images if empty."""
|
||||
if len(image_db.all()) == 0:
|
||||
@@ -91,6 +127,7 @@ def initializeImages():
|
||||
('boy03', IMAGE_TYPE_PROFILE, '.png', True),
|
||||
('boy04', IMAGE_TYPE_PROFILE, '.png', True),
|
||||
('broom', IMAGE_TYPE_ICON, '.png', True),
|
||||
('candy', IMAGE_TYPE_ICON, '.png', True),
|
||||
('computer-game', IMAGE_TYPE_ICON, '.png', True),
|
||||
('fighting', IMAGE_TYPE_ICON, '.png', True),
|
||||
('games-with-dad', IMAGE_TYPE_ICON, '.png', True),
|
||||
|
||||
4
main.py
4
main.py
@@ -10,7 +10,7 @@ from api.task_api import task_api
|
||||
from config.version import get_full_version
|
||||
from events.broadcaster import Broadcaster
|
||||
from events.sse import sse_response_for_user, send_to_user
|
||||
from db.default import initializeImages
|
||||
from db.default import initializeImages, createDefaultTasks, createDefaultRewards
|
||||
|
||||
# Configure logging once at application startup
|
||||
logging.basicConfig(
|
||||
@@ -63,6 +63,8 @@ def start_background_threads():
|
||||
# TODO: implement users
|
||||
os.makedirs(get_user_image_dir("user123"), exist_ok=True)
|
||||
initializeImages()
|
||||
createDefaultTasks()
|
||||
createDefaultRewards()
|
||||
start_background_threads()
|
||||
|
||||
|
||||
|
||||
BIN
resources/images/candy.png
Normal file
BIN
resources/images/candy.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
@@ -67,7 +67,6 @@ function handleChildRewardSet(event: Event) {
|
||||
|
||||
function handleRewardRequest(event: Event) {
|
||||
const payload = event.payload as ChildRewardRequestEventPayload
|
||||
console.log('Received child_reward_request event:', payload)
|
||||
const childId = payload.child_id
|
||||
const rewardId = payload.reward_id
|
||||
if (child.value && childId == child.value.id) {
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
Child,
|
||||
Event,
|
||||
Reward,
|
||||
RewardStatus,
|
||||
ChildTaskTriggeredEventPayload,
|
||||
ChildRewardTriggeredEventPayload,
|
||||
ChildRewardRequestEventPayload,
|
||||
@@ -36,6 +37,7 @@ const selectedReward = ref<Reward | null>(null)
|
||||
const childRewardListRef = ref()
|
||||
const childChoreListRef = ref()
|
||||
const childHabitListRef = ref()
|
||||
const showPendingRewardDialog = ref(false)
|
||||
|
||||
function handleTaskTriggered(event: Event) {
|
||||
const payload = event.payload as ChildTaskTriggeredEventPayload
|
||||
@@ -221,9 +223,50 @@ onUnmounted(() => {
|
||||
|
||||
const triggerTask = (task: Task) => {
|
||||
selectedTask.value = task
|
||||
const pendingRewardIds = childRewardListRef.value?.getPendingRewards()
|
||||
if (pendingRewardIds && pendingRewardIds.length > 0) {
|
||||
showPendingRewardDialog.value = true
|
||||
return
|
||||
}
|
||||
showConfirm.value = true
|
||||
}
|
||||
|
||||
async function cancelRewardById(rewardId: string) {
|
||||
if (!child.value?.id) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await fetch(`/api/child/${child.value.id}/cancel-request-reward`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ reward_id: rewardId }),
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(`Failed to cancel reward ID ${rewardId}:`, err)
|
||||
}
|
||||
}
|
||||
|
||||
async function cancelPendingReward() {
|
||||
if (!child.value?.id) {
|
||||
showPendingRewardDialog.value = false
|
||||
return
|
||||
}
|
||||
try {
|
||||
const pendingRewardIds = childRewardListRef.value?.getPendingRewards()
|
||||
await Promise.all(pendingRewardIds?.map((id: string) => cancelRewardById(id)) || [])
|
||||
childRewardListRef.value?.refresh()
|
||||
} catch (err) {
|
||||
console.error('Failed to cancel pending reward:', err)
|
||||
} finally {
|
||||
showPendingRewardDialog.value = false
|
||||
// After cancelling, proceed to trigger the task if one was selected
|
||||
console.log('Proceeding to trigger task after cancelling pending rewards.', selectedTask.value)
|
||||
if (selectedTask.value) {
|
||||
showConfirm.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const confirmTriggerTask = async () => {
|
||||
if (!child.value?.id || !selectedTask.value) return
|
||||
try {
|
||||
@@ -333,6 +376,22 @@ const childId = computed(() => child.value?.id ?? null)
|
||||
Assign Rewards
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Pending Reward Dialog -->
|
||||
<div v-if="showPendingRewardDialog" class="modal-backdrop">
|
||||
<div class="modal">
|
||||
<div class="dialog-message" style="margin-bottom: 1.2rem">
|
||||
There is a pending reward request. The reward must be cancelled before triggering a new
|
||||
task.<br />
|
||||
Would you like to cancel the pending reward?
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button @click="cancelPendingReward">Yes, Cancel Reward</button>
|
||||
<button @click="showPendingRewardDialog = false">No</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showConfirm && selectedTask" class="modal-backdrop">
|
||||
<div class="modal">
|
||||
<div class="task-info">
|
||||
|
||||
@@ -127,13 +127,17 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
function getPendingRewards(): string[] {
|
||||
return rewards.value.filter((r) => r.redeeming).map((r) => r.id)
|
||||
}
|
||||
|
||||
// revoke created object URLs when component unmounts to avoid memory leaks
|
||||
onBeforeUnmount(() => {
|
||||
revokeAllImageUrls()
|
||||
})
|
||||
|
||||
// expose refresh method for parent component
|
||||
defineExpose({ refresh: () => fetchRewards(props.childId) })
|
||||
defineExpose({ refresh: () => fetchRewards(props.childId), getPendingRewards })
|
||||
|
||||
const isAnyPending = computed(() => rewards.value.some((r) => r.redeeming))
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user