composables, align with updated API
- Replace deleted Pinia stores with
module-level singleton composables
(useAuth, useChat, useFeed, useUi) — all
return reactive({...}) so
Refs auto-unwrap in both templates and
script code
- Align entire codebase with new
swagger-generated api.ts types:
· TagDto.value (was .name) — FeedCard,
FeedFilters, ProfileEditor,
ProfileSetupView, MyProfileView,
ProfileDetailView, useUi
· MediaItemDto[] / .path (was mediaUrls[],
avatarUrl) — FeedCard,
FeedView, MyProfileView,
ProfileDetailView
· ChatDto.status 'active'|'closed' (was
isActive: boolean) —
ChatRoomView, ChatsListView
· MessageDto.profileId (was senderId) —
ChatRoomView, ChatBubble
· MeResponseDto → fetchMe now calls /me +
/profiles/my in parallel
· Token refresh: res.data.data.accessToken
(nested wrapper) —
router/index.ts aligned with client.ts
interceptor
- Fix FeedCard, ChatBubble imports pointing
to deleted store files
- Fix ProfileSetupView form type to avoid
string|undefined on v-model
- Fix history.back() → window.history.back()
via goBack() helper
- Fix chat.unreadCount possibly-undefined
guard in ChatsListView
- Fix MapPicker Leaflet icon cast (as unknown
as Record<string, unknown>)
83 lines
1.8 KiB
TypeScript
83 lines
1.8 KiB
TypeScript
import { ref, reactive } from 'vue';
|
|
|
|
export type ToastType = 'success' | 'error' | 'info' | 'warning';
|
|
|
|
export interface Toast {
|
|
id: string;
|
|
type: ToastType;
|
|
message: string;
|
|
duration?: number;
|
|
}
|
|
|
|
export interface Tag {
|
|
id: string;
|
|
value: string;
|
|
}
|
|
|
|
export interface City {
|
|
id: string;
|
|
name: string;
|
|
}
|
|
|
|
export interface District {
|
|
id: string;
|
|
name: string;
|
|
cityId: string;
|
|
}
|
|
|
|
export interface Greeting {
|
|
id: string;
|
|
text: string;
|
|
}
|
|
|
|
const toasts = ref<Toast[]>([]);
|
|
const sidebarExpanded = ref(false);
|
|
const tags = ref<Tag[]>([]);
|
|
const cities = ref<City[]>([]);
|
|
const districts = reactive<Record<string, District[]>>({});
|
|
const greetings = ref<Greeting[]>([]);
|
|
const referencesLoaded = ref(false);
|
|
|
|
function addToast(message: string, type: ToastType = 'info', duration = 4000) {
|
|
const id = `${Date.now()}-${Math.random()}`;
|
|
toasts.value.push({ id, type, message, duration });
|
|
if (duration > 0) {
|
|
setTimeout(() => removeToast(id), duration);
|
|
}
|
|
return id;
|
|
}
|
|
|
|
function removeToast(id: string) {
|
|
toasts.value = toasts.value.filter((t) => t.id !== id);
|
|
}
|
|
|
|
function setSidebarExpanded(value: boolean) {
|
|
sidebarExpanded.value = value;
|
|
}
|
|
|
|
function setTags(data: Tag[]) { tags.value = data; }
|
|
function setCities(data: City[]) { cities.value = data; }
|
|
function setDistricts(cityId: string, data: District[]) { districts[cityId] = data; }
|
|
function setGreetings(data: Greeting[]) { greetings.value = data; }
|
|
function setReferencesLoaded() { referencesLoaded.value = true; }
|
|
|
|
export function useUi() {
|
|
return reactive({
|
|
toasts,
|
|
sidebarExpanded,
|
|
tags,
|
|
cities,
|
|
districts,
|
|
greetings,
|
|
referencesLoaded,
|
|
addToast,
|
|
removeToast,
|
|
setSidebarExpanded,
|
|
setTags,
|
|
setCities,
|
|
setDistricts,
|
|
setGreetings,
|
|
setReferencesLoaded,
|
|
});
|
|
}
|