feat: taste onboarding for new listeners (M6)
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m2s
ci / db / db (push) Failing after 1m29s
ci / ts / ts (packages + web) (push) Successful in 49s
ci / api / api (push) Successful in 1m25s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 48s
ci / recommender / recommender (push) Successful in 21s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m2s
ci / db / db (push) Failing after 1m29s
ci / ts / ts (packages + web) (push) Successful in 49s
ci / api / api (push) Successful in 1m25s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 48s
ci / recommender / recommender (push) Successful in 21s
- GET /onboarding offers the library's top artists (with album covers) and genres and says whether to show it (not done and < 10 plays); PUT /me/onboarding stores the choice or a skip (migration 00009). - The recommender seeds the taste from it while the user has fewer than 30 scored tracks: chosen artists' tracks +1, chosen genres +0.5. - Web: onboarding replaces the wave on the home page until done or skipped; artist grid with covers, genre chips, at least 3 artists. - e2e journey and the recommender DB test cover it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ff0aafdb1e
commit
fb07f962eb
14 files changed
+1137
-238
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { unwrap } from '@pipu/core';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
import { cx, FormError, Icon } from '../shared/ui/ui';
|
||||
import { WaveButton } from '../widgets/wave/WaveButton';
|
||||
import s from './home.module.css';
|
||||
import { Onboarding } from './Onboarding';
|
||||
|
||||
/** Иконки Material Symbols по именам из /wave/options. */
|
||||
const ICONS: Record<string, string> = {
|
||||
@@ -44,8 +45,28 @@ const WAVE_COLORS: [string, string, string] = ['#2F80FF', '#7C5CFF', '#35D3FF'];
|
||||
|
||||
type Tr = (key: string) => string;
|
||||
|
||||
/** Главная (раскладка Center): кнопка «Моя волна» и под ней выбор занятия и настроения. */
|
||||
/** Главная: для нового пользователя без истории — сначала онбординг вкуса, затем волна. */
|
||||
export function HomePage() {
|
||||
const session = useSession();
|
||||
const queryClient = useQueryClient();
|
||||
const onboarding = useQuery({
|
||||
queryKey: ['onboarding'],
|
||||
queryFn: async () => unwrap(await session.client.GET('/api/v1/onboarding')),
|
||||
staleTime: Infinity,
|
||||
});
|
||||
if (onboarding.data?.required) {
|
||||
return (
|
||||
<Onboarding
|
||||
options={onboarding.data}
|
||||
onDone={() => queryClient.setQueryData(['onboarding'], { ...onboarding.data, required: false })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return <WaveHome />;
|
||||
}
|
||||
|
||||
/** Главная (раскладка Center): кнопка «Моя волна» и под ней выбор занятия и настроения. */
|
||||
function WaveHome() {
|
||||
const { t } = useTranslation();
|
||||
const tr = t as unknown as Tr;
|
||||
const session = useSession();
|
||||
|
||||
Reference in new issue
Block a user