feat: implement advanced reward management and wheel customization

- Add customizable background color
- Add wheel animations and sound effects
- Add reward description field and winner modal
- Change font to Dana
- Add configurable reward probabilities
- Support reward types (Empty, Discount Code, LiveCoin)
- Replace reward title with reward type selector
- Allow wheel page title customization from admin panel
This commit is contained in:
2026-06-10 14:55:07 +03:30
parent b0ff339525
commit ec86cdc528
26 changed files with 1166 additions and 533 deletions

View File

@@ -1,40 +1,74 @@
const BASE = 'http://127.0.0.1:8000';
// ---------------- USER ----------------
export const getItems = () =>
fetch(`${BASE}/user/items`)
.then(r => r.json());
fetch(`${BASE}/user/items`).then(r => r.json());
export const spinWheel = () =>
fetch(`${BASE}/user/spin`, {
method: 'POST'
}).then(r => r.json());
fetch(`${BASE}/user/spin`, { method: 'POST' }).then(async (r) => {
if (!r.ok) throw new Error('Spin failed');
return r.json();
});
// ---------------- ADMIN ----------------
export const adminGetItems = () =>
fetch(`${BASE}/admin/items`)
.then(r => r.json());
fetch(`${BASE}/admin/items`).then(r => r.json());
export const createItem = (data) =>
fetch(`${BASE}/admin/items`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: data.title,
prize: data.prize,
prize_type: data.prize_type,
description: data.description,
probability: data.probability
})
}).then(r => r.json());
export const updateItem = (id, data) =>
fetch(`${BASE}/admin/items/${id}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
title: data.title,
prize: data.prize,
prize_type: data.prize_type,
description: data.description,
probability: data.probability
})
}).then(r => r.json());
export const deleteItem = (id) =>
fetch(`${BASE}/admin/items/${id}`, {
method: 'DELETE'
}).then(r => {
if (r.status === 204) return {};
return r.json();
});
fetch(`${BASE}/admin/items/${id}`, { method: 'DELETE' }).then(async (r) => {
if (!r.ok && r.status !== 204) throw new Error('Delete failed');
return {};
});
// ---------------- رنگ پس‌زمینه ----------------
export const getBgColor = () =>
localStorage.getItem('wheelBgColor') || '#7B241C';
export const saveBgColor = (color) => {
localStorage.setItem('wheelBgColor', color);
window.dispatchEvent(new StorageEvent('storage', {
key: 'wheelBgColor',
newValue: color
}));
};
// ---------------- عنوان صفحه گردونه ----------------
export const getTitleSettings = () => {
const saved = localStorage.getItem('wheelTitleSettings');
return saved ? JSON.parse(saved) : { text: 'گردونه شانس', color: '#FFD700' };
};
export const saveTitleSettings = (text, color) => {
const settings = { text, color };
localStorage.setItem('wheelTitleSettings', JSON.stringify(settings));
window.dispatchEvent(new StorageEvent('storage', {
key: 'wheelTitleSettings',
newValue: JSON.stringify(settings)
}));
};