Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove "active" protocol concept #58

Merged
merged 7 commits into from
Jan 23, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ export const ParticipantColumns =
return <DataTableColumnHeader column={column} title="Identifier" />;
},
},
{
accessorKey: 'Interview Count',
header: ({ column }) => {
return (
<DataTableColumnHeader column={column} title="Interview count" />
);
},
cell: ({ row }) => {
return <span>{row.original._count.interviews}</span>;
},
},
{
accessorKey: 'Unique_interview_URL',
header: ({ column }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { DeleteAllParticipantsButton } from '~/app/(dashboard)/dashboard/partici
import AddParticipantButton from '~/app/(dashboard)/dashboard/participants/_components/AddParticipantButton';
import { useState } from 'react';
import { DeleteParticipantsDialog } from '~/app/(dashboard)/dashboard/participants/_components/DeleteParticipantsDialog';

export const ParticipantsTable = ({
initialData,
}: {
Expand All @@ -26,6 +27,7 @@ export const ParticipantsTable = ({
},
},
);

const [participantsToDelete, setParticipantsToDelete] =
useState<ParticipantWithInterviews[]>();
const [showDeleteModal, setShowDeleteModal] = useState(false);
Expand Down

This file was deleted.

12 changes: 0 additions & 12 deletions app/(dashboard)/dashboard/_components/ProtocolsTable/Columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import { type ColumnDef, flexRender } from '@tanstack/react-table';
import { Checkbox } from '~/components/ui/checkbox';
import ActiveButton from './ActiveButton';
import { DataTableColumnHeader } from '~/components/DataTable/ColumnHeader';
import type { ProtocolWithInterviews } from '~/shared/types';
import { dateOptions } from '~/components/DataTable/helpers';
Expand All @@ -29,17 +28,6 @@ export const ProtocolColumns: ColumnDef<ProtocolWithInterviews>[] = [
enableSorting: false,
enableHiding: false,
},
{
id: 'active',
enableSorting: true,
accessorFn: (row) => row.active,
header: ({ column }) => (
<DataTableColumnHeader column={column} title="Active" />
),
cell: ({ row }) => (
<ActiveButton active={row.original.active} protocolId={row.original.id} />
),
},
{
accessorKey: 'name',
header: ({ column }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ export const ProtocolsTable = ({
filterColumnAccessorKey="name"
handleDeleteSelected={handleDelete}
actions={ActionsDropdown}
calculateRowClasses={(row) =>
row.original.active
? 'bg-purple-500/30 hover:bg-purple-500/40'
: undefined
}
/>
<DeleteProtocolsDialog
open={showAlertDialog}
Expand Down
145 changes: 145 additions & 0 deletions app/(dashboard)/dashboard/_components/RecruitmentTestSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
'use client';

import type { Participant, Protocol } from '@prisma/client';
import type { Route } from 'next';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import RecruitmentSwitch from '~/components/RecruitmentSwitch';
import { Button } from '~/components/ui/Button';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '~/components/ui/select';
import { api } from '~/trpc/client';
import { getBaseUrl } from '~/trpc/shared';

const RecruitmentTestSection = () => {
const router = useRouter();

const { data: appSettings, isLoading: isLoadingAppSettings } =
api.appSettings.get.useQuery();
const { data: protocolData, isLoading: isLoadingProtocols } =
api.protocol.get.all.useQuery();
const [protocols, setProtocols] = useState<Protocol[]>([]);
const [selectedProtocol, setSelectedProtocol] = useState<Protocol>();
const [selectedParticipant, setSelectedParticipant] = useState<Participant>();

const { data: participants, isLoading: isLoadingParticipants } =
api.participant.get.all.useQuery();

useEffect(() => {
if (protocolData) {
setProtocols(protocolData);
}
}, [protocolData]);

const allowAnonymousRecruitment = !!appSettings?.allowAnonymousRecruitment;

useEffect(() => {
if (allowAnonymousRecruitment) {
setSelectedParticipant(undefined);
}
}, [allowAnonymousRecruitment]);

if (isLoadingAppSettings) {
return <div>Loading...</div>;
}

const buttonDisabled =
!selectedProtocol || (!allowAnonymousRecruitment && !selectedParticipant);

const getInterviewURL = (): Route => {
if (!selectedParticipant) {
return `/onboard/${selectedProtocol?.id}` as Route;
}

return `/onboard/${selectedProtocol?.id}/?participantId=${selectedParticipant?.id}` as Route;
};

return (
<div className="flex flex-col gap-4 rounded-lg border border-muted p-6">
<h1 className="text-xl">Recruitment Test Section</h1>
<div className="flex justify-between">
<p>Allow anonymous recruitment?</p>
<RecruitmentSwitch />
</div>
<div className="flex gap-4">
<Select
onValueChange={(value) => {
const protocol = protocols.find(
(protocol) => protocol.id === value,
);

setSelectedProtocol(protocol);
}}
value={selectedProtocol?.id}
disabled={isLoadingProtocols}
>
<SelectTrigger>
<SelectValue placeholder="Select a Protocol..." />
</SelectTrigger>
<SelectContent>
{protocols?.map((protocol) => (
<SelectItem key={protocol.id} value={protocol.id}>
{protocol.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Select
onValueChange={(value) => {
const participant = participants?.find(
(participant) => participant.id === value,
);

setSelectedParticipant(participant);
}}
value={selectedParticipant?.id}
disabled={isLoadingParticipants}
>
<SelectTrigger>
<SelectValue placeholder="Select a Participant..." />
</SelectTrigger>
<SelectContent>
{participants?.map((participant) => (
<SelectItem key={participant.id} value={participant.id}>
{participant.identifier}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<Button
disabled={buttonDisabled}
onClick={() => router.push(getInterviewURL())}
>
Start Interview with GET
</Button>
<Button
disabled={buttonDisabled}
onClick={async () =>
await fetch(getBaseUrl() + getInterviewURL(), {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
participantId: selectedParticipant?.id,
}),
}).then((response) => {
if (response.redirected) {
window.location.href = response.url;
}
})
}
>
Start Interview with POST
</Button>
</div>
);
};

export default RecruitmentTestSection;
9 changes: 2 additions & 7 deletions app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import ResetButton from './_components/ResetButton';
import AnonymousRecruitmentSwitch from '~/components/AnonymousRecruitmentSwitch/AnonymousRecruitmentSwitch';
import Link from 'next/link';
import { Button } from '~/components/ui/Button';
import AnalyticsButton from './_components/AnalyticsButton';
import RecruitmentTestSection from './_components/RecruitmentTestSection';

function Home() {
return (
<>
<main className="mx-auto flex w-[80%] max-w-[1200px] flex-col gap-10 p-10">
<h1 className="mb-2 text-3xl font-bold">Welcome</h1>
<p>This is the main dashboard.</p>
<Link href="/interview/new">
<Button>Start anonymous interview</Button>
</Link>
<ResetButton />
<AnonymousRecruitmentSwitch />
<RecruitmentTestSection />
<AnalyticsButton />
</main>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ export const DeleteParticipantsDialog = ({
useEffect(() => {
setParticipantsInfo({
hasInterviews: participantsToDelete?.some(
(participant) => participant.interviews.length > 0,
(participant) => participant._count.interviews > 0,
),
hasUnexportedInterviews: participantsToDelete?.some((participant) =>
participant.interviews.some((interview) => !interview.exportTime),
),
});
}, [participantsToDelete]);

const { mutateAsync: deleteParticipants, isLoading: isDeleting } =
api.participant.delete.byId.useMutation({
onError(error) {
Expand Down
Loading