Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 42 additions & 31 deletions src/components/molecules/axis/AxisHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,44 +77,55 @@ export function AxisHeader({

<AnimatePresence>
{showDescription && (
<Portal>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-[9998] bg-black/60 backdrop-blur-sm md:hidden"
onClick={e => {
e.stopPropagation();
setShowDescription(false);
}}
/>
<>
<Portal>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
className="fixed inset-0 z-[9998] bg-black/60 backdrop-blur-sm md:hidden"
onClick={e => {
e.stopPropagation();
setShowDescription(false);
}}
/>
<motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 5, scale: 0.95 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
className="bg-popover text-popover-foreground border-border fixed top-1/2 left-1/2 z-[9999] w-[90vw] max-w-sm -translate-x-1/2 -translate-y-1/2 cursor-default rounded-xl border p-5 shadow-2xl md:hidden"
onClick={e => e.stopPropagation()}
>
<div className="mb-3 flex shrink-0 items-center justify-between">
<span className="text-sm font-bold tracking-wider uppercase">{tCommon('info')}</span>
<button
onClick={e => {
e.stopPropagation();
setShowDescription(false);
}}
className="text-muted-foreground hover:text-foreground"
>
<span className="material-symbols-outlined">close</span>
</button>
</div>
<p className="text-base leading-relaxed font-normal whitespace-pre-line">{axis.description}</p>
</motion.div>
</Portal>

<motion.div
initial={{ opacity: 0, y: 10, scale: 0.95 }}
initial={{ opacity: 0, y: 5, scale: 0.95 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 5, scale: 0.95 }}
transition={{ duration: 0.2, ease: 'easeOut' }}
className="bg-popover text-popover-foreground border-border fixed top-1/2 left-1/2 z-[9999] w-[90vw] max-w-sm -translate-x-1/2 -translate-y-1/2 cursor-default rounded-xl border p-5 shadow-2xl md:absolute md:top-auto md:left-auto md:w-[400px] md:translate-x-0 md:translate-y-0 md:p-4"
style={{}}
className="bg-popover text-popover-foreground border-border absolute bottom-full left-1/2 z-50 mb-2 hidden w-80 -translate-x-1/2 cursor-default rounded-xl border p-4 shadow-xl md:block"
onClick={e => e.stopPropagation()}
>
<div className="mb-3 flex shrink-0 items-center justify-between md:hidden">
<span className="text-sm font-bold tracking-wider uppercase">{tCommon('info')}</span>
<button
onClick={e => {
e.stopPropagation();
setShowDescription(false);
}}
className="text-muted-foreground hover:text-foreground"
>
<span className="material-symbols-outlined">close</span>
</button>
</div>
<p className="text-base leading-relaxed font-normal whitespace-pre-line md:text-sm">
{axis.description}
</p>
<p className="text-xs leading-relaxed font-normal whitespace-pre-line">{axis.description}</p>
<div className="bg-popover border-r-border border-b-border absolute -bottom-1 left-1/2 h-2 w-2 -translate-x-1/2 rotate-45 border-r border-b"></div>
</motion.div>
</Portal>
</>
)}
</AnimatePresence>
</div>
Expand Down
25 changes: 25 additions & 0 deletions src/components/organisms/Atlas/DiscoveryView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DiscoveryResultModal } from '@/components/molecules/DiscoveryResultModa
import { PageHeader } from '@/components/molecules/PageHeader';
import { DiscoveryListSkeleton } from '@/components/molecules/DiscoveryListSkeleton';
import { DiscoveryList } from './DiscoveryList';
import { motion, AnimatePresence } from 'framer-motion';

export function DiscoveryView() {
const t = useTranslations('Atlas');
Expand All @@ -22,6 +23,30 @@ export function DiscoveryView() {

<div className="mb-10">
<PageHeader title={t('discovery_title')} description={t('discovery_subtitle')} />

<AnimatePresence>
{state.isCalculating && (
<motion.div
initial={{ opacity: 0, height: 0, marginTop: 0 }}
animate={{ opacity: 1, height: 'auto', marginTop: 32 }}
exit={{ opacity: 0, height: 0, marginTop: 0 }}
className="w-full overflow-hidden"
>
<div className="text-muted-foreground/80 mb-2 flex justify-between px-1 text-[10px] font-bold tracking-wider uppercase">
<span>{t('affinity_pending')}...</span>
<span>{state.progress}%</span>
</div>
<div className="bg-secondary/50 h-2 w-full overflow-hidden rounded-full backdrop-blur-sm">
<motion.div
className="bg-primary h-full rounded-full"
initial={{ width: 0 }}
animate={{ width: `${state.progress}%` }}
transition={{ ease: 'linear', duration: 0.2 }}
/>
</div>
</motion.div>
)}
</AnimatePresence>
</div>

<div className="min-h-[500px]">
Expand Down
19 changes: 19 additions & 0 deletions src/hooks/controllers/useDiscoveryController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export function useDiscoveryController() {
const [winner, setWinner] = useState<IdeologyList | null>(null);
const [isModalOpen, setIsModalOpen] = useState(false);

const [progress, setProgress] = useState(0);
const [isCalculating, setIsCalculating] = useState(true);

const getRelevantScore = useCallback((affinityData?: IdeologyAffinity) => {
if (!affinityData) return 0;

Expand Down Expand Up @@ -48,6 +51,9 @@ export function useDiscoveryController() {

const init = async () => {
try {
setIsCalculating(true);
setProgress(0);

const ideologiesResponse = await IdeologiesService.ideologiesList(undefined, 100);
if (!mounted) return;

Expand Down Expand Up @@ -92,6 +98,12 @@ export function useDiscoveryController() {
const total = ideologiesResponse.results.length;
let currentAffinitiesRef: Record<string, IdeologyAffinity> = {};

if (total === 0) {
setIsCalculating(false);
setProgress(100);
return;
}

ideologiesResponse.results.forEach(ideology => {
IdeologiesService.ideologiesAffinityRetrieve(ideology.uuid, completedAnswerUuid)
.then(affinityData => {
Expand All @@ -105,8 +117,10 @@ export function useDiscoveryController() {

setLoadingMap(prev => ({ ...prev, [ideology.uuid]: false }));
completedCount++;
setProgress(Math.round((completedCount / total) * 100));

if (completedCount === total) {
setIsCalculating(false);
setTimeout(() => finishDiscovery(ideologiesResponse.results, currentAffinitiesRef), 500);
}
})
Expand All @@ -115,15 +129,18 @@ export function useDiscoveryController() {
if (!mounted) return;
setLoadingMap(prev => ({ ...prev, [ideology.uuid]: false }));
completedCount++;
setProgress(Math.round((completedCount / total) * 100));

if (completedCount === total) {
setIsCalculating(false);
setTimeout(() => finishDiscovery(ideologiesResponse.results, currentAffinitiesRef), 500);
}
});
});
} catch (error) {
console.error(error);
setIsGlobalLoading(false);
setIsCalculating(false);
}
};

Expand Down Expand Up @@ -175,6 +192,8 @@ export function useDiscoveryController() {
winner,
isModalOpen,
getRelevantScore,
progress,
isCalculating,
},
actions: {
closeModal: () => setIsModalOpen(false),
Expand Down
15 changes: 11 additions & 4 deletions src/hooks/features/atlas/useAxisInteraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,19 @@ export function useAxisInteraction({ axisUuid, answerData, onSave, onDelete, rea

const maxMarginLeft = value + 100;
const maxMarginRight = 100 - value;
const safeMargin = Math.min(targetMargin, maxMarginLeft, maxMarginRight);

setMarginLeft(safeMargin);
setMarginRight(safeMargin);
const newMarginLeft = Math.min(targetMargin, maxMarginLeft);
const newMarginRight = Math.min(targetMargin, maxMarginRight);

commitSave({ value, margin_left: safeMargin, margin_right: safeMargin, is_indifferent: false });
setMarginLeft(newMarginLeft);
setMarginRight(newMarginRight);

commitSave({
value,
margin_left: newMarginLeft,
margin_right: newMarginRight,
is_indifferent: false,
});
},
[readOnly, value, commitSave],
);
Expand Down