Skip to content

Commit

Permalink
somewhat working stage index syncing
Browse files Browse the repository at this point in the history
  • Loading branch information
jthrilly committed Dec 8, 2023
1 parent 76050bc commit 4af084a
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 216 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export const ParticipantColumns =
cell: ({ row }) => (
<Link
className="text-blue-500 underline hover:text-blue-300"
href={`/participant/${row.original.id}`}
href={`/interview/new?identifier=${row.original.id}`}
>
Participant page
Participant link
</Link>
),
enableSorting: false,
Expand Down
1 change: 1 addition & 0 deletions app/(interview)/interview/[interviewId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default async function Page({
<div className="flex h-[100vh] max-h-[100vh] flex-col bg-[var(--nc-background)] text-[var(--nc-text)]">
<NoSSRWrapper>
<InterviewShell
interviewID={interviewId}
serverProtocol={protocol}
serverSession={serverSession}
/>
Expand Down
38 changes: 35 additions & 3 deletions app/(interview)/interview/_components/InterviewShell.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,62 @@
'use client';

import { Provider } from 'react-redux';
import { Provider, useSelector } from 'react-redux';
import DialogManager from '~/lib/interviewer/components/DialogManager';
import ProtocolScreen from '~/lib/interviewer/containers/ProtocolScreen';
import { store } from '~/lib/interviewer/store';
import UserBanner from './UserBanner';
import { useEffect, useState } from 'react';
import { parseAsInteger, useQueryState } from 'next-usequerystate';
import type { Protocol } from '@codaco/shared-consts';
import type { ServerSession } from '../[interviewId]/page';
import {
SET_SERVER_SESSION,
type SetServerSessionAction,
} from '~/lib/interviewer/ducks/modules/setServerSession';
import { getStageIndex } from '~/lib/interviewer/selectors/session';
import { api } from '~/trpc/client';

// The job of ServerSync is to listen to actions in the redux store, and to sync
// data with the server.
const ServerSync = ({ interviewId }: { interviewId: string }) => {
const [init, setInit] = useState(false);
// Current stage
const currentStage = useSelector(getStageIndex);
const { mutate: updateStage } =
api.interview.sync.updateStageIndex.useMutation();

useEffect(() => {
if (!init) {
setInit(true);
return;
}

console.log(`⬆️ Syncing stage index (${currentStage}) to server...`);
updateStage({ interviewId, stageIndex: currentStage });
}, [currentStage, updateStage, interviewId, init]);

return null;
};

// The job of interview shell is to receive the server-side session and protocol
// and create a redux store with that data.
// Eventually it will handle syncing this data back.
const InterviewShell = ({
interviewID,
serverProtocol,
serverSession,
}: {
interviewID: string;
serverProtocol: Protocol;
serverSession: ServerSession;
}) => {
const [loading, setLoading] = useState(true);
const [init, setInit] = useState(false);

useEffect(() => {
if (init) {
return;
}

store.dispatch<SetServerSessionAction>({
type: SET_SERVER_SESSION,
payload: {
Expand All @@ -35,14 +65,16 @@ const InterviewShell = ({
},
});
setLoading(false);
}, [serverSession, serverProtocol]);
setInit(true);
}, [serverSession, serverProtocol, init]);

if (loading) {
return 'Second loading stage...';
}

return (
<Provider store={store}>
<ServerSync interviewId={interviewID} />
<UserBanner />
<ProtocolScreen />
<DialogManager />
Expand Down
12 changes: 5 additions & 7 deletions app/(interview)/interview/new/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default async function Page({
// Anonymous recruitment is enabled

// Use the identifier from the URL, or generate a new one
const identifier = searchParams.identifier || faker.string.uuid();
const identifier = searchParams.identifier ?? faker.string.uuid();

// Validate the identifier
const isValid = participantIdentifierSchema.parse(identifier);
Expand All @@ -55,15 +55,13 @@ export default async function Page({
}

// Create the interview
const { error, createdInterview } =
const { createdInterviewId, error } =
await api.interview.create.mutate(identifier);

if (error || !createdInterview) {
throw new Error(error || 'An error occurred while creating the interview');
if (error) {
throw new Error('An error occurred while creating the interview');
}

// TODO: check if the identifier already exists.

// Redirect to the interview/[id] route
redirect(`/interview/${createdInterview.id}`);
redirect(`/interview/${createdInterviewId}`);
}
10 changes: 1 addition & 9 deletions lib/interviewer/behaviours/DragAndDrop/DropTarget.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const dropTarget = (WrappedComponent) => {
onDrag,
onDragEnd,
accepts,
meta: meta(),
meta: meta?.(),
width: boundingClientRect.width,
height: boundingClientRect.height,
y: boundingClientRect.top,
Expand Down Expand Up @@ -96,14 +96,6 @@ const dropTarget = (WrappedComponent) => {
meta: PropTypes.func,
};

DropTarget.defaultProps = {
meta: () => ({}),
accepts: () => false,
onDrop: () => {},
onDrag: () => {},
onDragEnd: () => {},
};

return DropTarget;
};

Expand Down
11 changes: 10 additions & 1 deletion lib/interviewer/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const useNavigationHelpers = (

const {
progress,
stageIndex,
isLastPrompt,
isFirstPrompt,
isLastStage,
Expand Down Expand Up @@ -94,6 +95,14 @@ const useNavigationHelpers = (
dispatch(sessionActions.updateStage(currentStage));
}, [currentStage, dispatch]);

// If currentStage is null, this is the first run. We need to set it based on
// the sessions current stage index.
useEffect(() => {
if (currentStage === null) {
setCurrentStage(stageIndex);
}
}, [currentStage, setCurrentStage, stageIndex]);

return {
progress,
isReadyForNextStage,
Expand Down Expand Up @@ -139,7 +148,7 @@ const NavigationButton = ({
const Navigation = () => {
const [currentStage, setCurrentStage] = useQueryState(
'stage',
parseAsInteger.withDefault(1),
parseAsInteger,
);

const {
Expand Down
Loading

0 comments on commit 4af084a

Please sign in to comment.