point history

This commit is contained in:
='fauz 2025-10-23 18:20:58 +07:00
parent 441f8f6a09
commit 22224c8003
3 changed files with 102 additions and 67 deletions

View File

@ -25,39 +25,41 @@
<!-- Form --> <!-- Form -->
<div class="w-full"> <div class="w-full">
<div class="mb-4"> <form @submit.prevent="login">
<input <div class="mb-4">
v-model="username" <input
placeholder="Username" v-model="username"
type="text" placeholder="Username"
class="w-full h-12 px-4 py-2 text-gray-700 bg-gray-50 border border-gray-300 rounded-2xl type="text"
focus:outline-none focus:ring-2 focus:ring-lime-400 focus:border-lime-400" class="w-full h-12 px-4 py-2 text-gray-700 bg-gray-50 border border-gray-300 rounded-2xl
/> focus:outline-none focus:ring-2 focus:ring-lime-400 focus:border-lime-400"
</div> />
</div>
<div class="mb-6"> <div class="mb-6">
<input <input
v-model="password" v-model="password"
type="password" type="password"
placeholder="Password" placeholder="Password"
class="w-full h-12 px-4 py-2 text-gray-700 bg-gray-50 border border-gray-300 rounded-2xl class="w-full h-12 px-4 py-2 text-gray-700 bg-gray-50 border border-gray-300 rounded-2xl
focus:outline-none focus:ring-2 focus:ring-lime-400 focus:border-lime-400" focus:outline-none focus:ring-2 focus:ring-lime-400 focus:border-lime-400"
/> />
</div> </div>
<button <button
@click="login" @click="login"
class="w-full h-12 bg-lime-500 text-white font-semibold rounded-2xl class="w-full h-12 bg-lime-500 text-white font-semibold rounded-2xl
hover:bg-lime-400 transition-all focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-lime-500" hover:bg-lime-400 transition-all focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-lime-500"
> >
LOGIN LOGIN
</button> </button>
<div class="w-full flex items-center justify-center mt-4"> <div class="w-full flex items-center justify-center mt-4">
<router-link to="/register" class="text-blue-600 font-semibold hover:underline"> <router-link to="/register" class="text-blue-600 font-semibold hover:underline">
REGISTER REGISTER
</router-link> </router-link>
</div> </div>
</form>
</div> </div>
</div> </div>
</div> </div>

View File

@ -28,7 +28,7 @@
<div class="p-4 flex justify-center"> <div class="p-4 flex justify-center">
<div class="bg-gradient-to-b from-gray-400 to-slate-500 rounded-2xl p-6 text-center w-full max-w-sm shadow-lg backdrop-blur-md animate-[pulse_3s_infinite]"> <div class="bg-gradient-to-b from-gray-400 to-slate-500 rounded-2xl p-6 text-center w-full max-w-sm shadow-lg backdrop-blur-md animate-[pulse_3s_infinite]">
<p class="text-md text-black font-bold">Total Poin </p> <p class="text-md text-black font-bold">Total Poin </p>
<h2 class="text-4xl font-bold text-yellow-300">{{ totalPoints }}</h2> <h2 class="text-4xl font-bold text-yellow-300">{{ myTotalPoint }}</h2>
</div> </div>
</div> </div>
@ -56,15 +56,15 @@
class="flex justify-between items-center bg-white bg-opacity-15 backdrop-blur-md rounded-xl p-4 shadow hover:bg-opacity-25 transition-all" class="flex justify-between items-center bg-white bg-opacity-15 backdrop-blur-md rounded-xl p-4 shadow hover:bg-opacity-25 transition-all"
> >
<div> <div>
<h3 class="font-semibold text-black">{{ entry.activity }} {{ index }}</h3> <h3 class="font-semibold text-black">{{ entry.mission?.name || 'Unknown Mission'}} {{ index }}</h3>
<p class="text-sm text-black">{{ entry.source }}</p> <p class="text-sm text-black">{{ entry.mission?.category }}</p>
<p class="text-xs text-black">{{ entry.date }}</p> <p class="text-xs text-black">{{ entry.completed_at }}</p>
</div> </div>
<span <span
class="font-bold text-lg" class="font-bold text-lg"
:class="entry.points > 0 ? 'text-orange-300' : 'text-red-300'" :class="entry.points > 0 ? 'text-orange-300' : 'text-red-300'"
> >
{{ entry.points > 0 ? '+' : '' }}{{ entry.points }} {{ entry.points > 0 ? '+' : '' }}{{ entry.point }}
</span> </span>
</div> </div>
</transition-group> </transition-group>
@ -87,33 +87,54 @@ export default{
} }
</script> </script>
<script setup> <script setup>
import { ref, computed } from "vue"; import { ref, computed, onMounted } from "vue";
import { getUserPoint } from "@/services/missions";
// Data contoh (bisa diganti dari backend) const myTotalPoint = ref(0);
const pointHistory = ref([
{ id: 1, activity: "Menang Game Word Spells", source: "Game", points: 30, date: "2025-10-21 10:22" },
{ id: 2, activity: "Membaca artikel motivasi", source: "Content", points: 10, date: "2025-10-21 12:00" },
{ id: 3, activity: "Membaca manga positif", source: "Manga", points: 15, date: "2025-10-22 09:15" },
{ id: 4, activity: "Kehilangan streak harian", source: "Penalty", points: -5, date: "2025-10-22 09:20" },
{ id: 5, activity: "Menjawab quiz refleksi diri", source: "Quiz", points: 25, date: "2025-10-22 11:30" },
]);
// Filter kategori // Data contoh (bisa diganti dari backend)
const categories = ["Semua", "Game", "Content", "Manga", "Quiz", "Penalty"]; const pointHistory = ref([
const selectedCategory = ref("Semua"); { id: 1, activity: "Menang Game Word Spells", source: "Game", points: 30, date: "2025-10-21 10:22" },
{ id: 2, activity: "Membaca artikel motivasi", source: "Content", points: 10, date: "2025-10-21 12:00" },
{ id: 3, activity: "Membaca manga positif", source: "Manga", points: 15, date: "2025-10-22 09:15" },
{ id: 4, activity: "Kehilangan streak harian", source: "Penalty", points: -5, date: "2025-10-22 09:20" },
{ id: 5, activity: "Menjawab quiz refleksi diri", source: "Quiz", points: 25, date: "2025-10-22 11:30" },
]);
// Hitung total poin // Filter kategori
const totalPoints = computed(() => const categories = ["Semua", "Game", "Content", "Manga", "Quiz", "Penalty"];
pointHistory.value.reduce((sum, e) => sum + e.points, 0) const selectedCategory = ref("Semua");
);
// Filter sesuai kategori // Hitung total poin
const filteredHistory = computed(() => { // const totalPoints = computed(() =>
if (selectedCategory.value === "Semua") return pointHistory.value; // pointHistory.value.reduce((sum, e) => sum + e.points, 0)
return pointHistory.value.filter( // );
e => e.source.toLowerCase() === selectedCategory.value.toLowerCase()
// Filter sesuai kategori
const filteredHistory = computed(() => {
if (selectedCategory.value === "Semua") return pointHistory.value;
return pointHistory.value.filter(
e => e.category.toLowerCase() === selectedCategory.value.toLowerCase()
);
});
const totalPoints = computed(() =>
pointHistory.value.reduce((sum, e) => sum + e.point, 0)
); );
});
async function getHistory(){
const histories = await getUserPoint();
const myPointHistory = histories.myTask;
myTotalPoint.value =totalPoints //histories.myTaskCount
pointHistory.value = myPointHistory
}
onMounted(() => {
getHistory();
});
</script> </script>
<style scoped> <style scoped>

View File

@ -17,6 +17,7 @@ export const getMissions = async () => {
...data, ...data,
count: activeMissions.length, count: activeMissions.length,
results: activeMissions, results: activeMissions,
allMissions: missions
}; };
}; };
@ -45,22 +46,33 @@ export const updateMissionLog = async(missionId ,data = {}) =>{
}); });
} }
export const getUserPoint = async() =>{ export const getUserPoint = async() =>{
const auth = useAuthStore(); const auth = useAuthStore();
const user = auth.user const user = auth.user
console.log(`User Data: ${JSON.stringify(user)}`) const [missions, missionLogs] = await Promise.all([getMissions(), getMissionLogs()]);
const userLogs = missionLogs.results.filter((mlog) => mlog.user_id === user.id);
// getting points const combine = userLogs.map(
const resPoint = await getMissionLogs(); log => {
console.log(`Missions Logs: ${JSON.stringify(resPoint)}`) const missionDetail = missions.allMissions.find((mission) => mission.id === log.mission);
const userLogs = resPoint.results.filter((log) => log.user_id === user.id);
const myPoints = userLogs.reduce((total, log) => total + log.point, 0); return {
...log,
mission: missionDetail || null
}
}
);
const myPoints = combine.reduce((total, log) => total + log.point, 0);
const activeMissions = missions.activeMissions || [];
const taskCount = activeMissions.length;
return { return {
task: resPoint, task: activeMissions,
taskCount: resPoint.count, taskCount: taskCount,
myTask: userLogs, myTask: combine,
myTaskCount: userLogs.length, myTaskCount: combine.length,
myPoints, myPoints,
}; };
} }