Consolidate prediction functionality by merging /api/prediction endpoint into /api/stations response. Move prediction logic from PredictionController into StationController, returning prediction data alongside station results. Replace usePrediction composable with unified useStations that returns {stations, meta, prediction}. Remove PredictionRequest, related tests, and unused Vue components (FuelFinderTest, MapTest, RecommendationTest, StationListTest). Add PredictionFull component and UpsellBanner. Extend NationalFuelPredictionService to include weekly_summary (7-day series, yesterday/today averages, cheapest/priciest days) and oil signal from price_predictions table. Update Home.vue to consume prediction from stations response. Add Plan::resolveCadenceForUser helper and configure Cashier to use custom Subscription model.
99 lines
2.2 KiB
JavaScript
99 lines
2.2 KiB
JavaScript
import { ref, computed } from 'vue'
|
|
import api from '../axios.js'
|
|
|
|
const user = ref(null)
|
|
const loading = ref(false)
|
|
const fetched = ref(false)
|
|
|
|
export function useAuth() {
|
|
const isAuthenticated = computed(() => user.value !== null)
|
|
|
|
const userTier = computed(() => {
|
|
if (!user.value) {
|
|
return 'guest'
|
|
}
|
|
return user.value.tier ?? 'free'
|
|
})
|
|
|
|
const isPaidTier = computed(() => {
|
|
return ['basic', 'plus', 'pro'].includes(userTier.value)
|
|
})
|
|
|
|
const subscriptionCancelled = computed(() => {
|
|
return user.value?.subscription_cancelled ?? false
|
|
})
|
|
|
|
const subscriptionCadence = computed(() => {
|
|
return user.value?.subscription_cadence ?? null
|
|
})
|
|
|
|
const subscribedAt = computed(() => {
|
|
return user.value?.subscribed_at ?? null
|
|
})
|
|
|
|
const subscriptionExpiresAt = computed(() => {
|
|
return user.value?.subscription_expires_at ?? null
|
|
})
|
|
|
|
async function fetchUser() {
|
|
if (fetched.value) {
|
|
return
|
|
}
|
|
loading.value = true
|
|
try {
|
|
const response = await api.get('/auth/me')
|
|
user.value = response.data
|
|
} catch {
|
|
user.value = null
|
|
} finally {
|
|
loading.value = false
|
|
fetched.value = true
|
|
}
|
|
}
|
|
|
|
function clearUser() {
|
|
user.value = null
|
|
fetched.value = false
|
|
}
|
|
|
|
async function logout() {
|
|
try {
|
|
await api.post('/auth/logout')
|
|
} finally {
|
|
clearUser()
|
|
}
|
|
}
|
|
|
|
async function updateProfile(data) {
|
|
const response = await api.put('/user/profile', data)
|
|
user.value = response.data
|
|
}
|
|
|
|
async function updatePassword(data) {
|
|
await api.put('/user/password', data)
|
|
}
|
|
|
|
async function deleteAccount(password) {
|
|
await api.delete('/user', { data: { password } })
|
|
clearUser()
|
|
}
|
|
|
|
return {
|
|
user,
|
|
loading,
|
|
isAuthenticated,
|
|
userTier,
|
|
isPaidTier,
|
|
subscriptionCancelled,
|
|
subscriptionCadence,
|
|
subscribedAt,
|
|
subscriptionExpiresAt,
|
|
fetchUser,
|
|
clearUser,
|
|
logout,
|
|
updateProfile,
|
|
updatePassword,
|
|
deleteAccount,
|
|
}
|
|
}
|