Skip to content

Commit

Permalink
add teams wip
Browse files Browse the repository at this point in the history
  • Loading branch information
xvvvyz committed Oct 29, 2024
1 parent 725ef9e commit a7d2e33
Show file tree
Hide file tree
Showing 39 changed files with 537 additions and 162 deletions.
4 changes: 2 additions & 2 deletions app/(pages)/(with-nav)/subjects/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ const Page = async () => {
) : (
<div>
Create a new <span className="text-fg-2">subject</span> using
the big yellow
the yellow
<br />
<div className="mr-1.5 inline-flex size-4 items-center justify-center rounded-full bg-accent-1 text-bg-1">
<PlusIcon className="inline w-3 stroke-2" />
</div>
button. Let&rsquo;s make positive change.
button. Let&rsquo;s make changes.
</div>
)}
</Empty>
Expand Down
29 changes: 14 additions & 15 deletions app/(pages)/@modal/(layout)/hey/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@ const Page = async () => {
title={`Hey, ${user.user_metadata.first_name}!`}
/>
<div className="px-4 pb-8 sm:px-8">
<div className="prose">
<div className="prose max-w-[26rem]">
<p>
At llog, our mission is to empower behavior professionals and their
clients by crafting intuitive and effective software tools that make
lasting behavior change more&nbsp;attainable.
</p>
<p className="max-w-[25rem]">
Your feedback is invaluable as we evolve and improve. Whether you
have thoughts, ideas, concerns or even dreams:{' '}
<Button href="mailto:[email protected]" variant="link">
email us
</Button>{' '}
or{' '}
<Button href="https://cal.com/llogapp/chat" variant="link">
schedule a call
</Button>
.
clients with tools that make lasting behavior change
more&nbsp;attainable. Your feedback is invaluable as we evolve and
improve. Whether you have thoughts, ideas, concerns or even dreams:{' '}
<span className="whitespace-nowrap">
<Button href="mailto:[email protected]" variant="link">
email us
</Button>{' '}
or{' '}
<Button href="https://cal.com/llogapp/chat" variant="link">
book a call
</Button>
.
</span>
</p>
<p>Happy behavior hacking!</p>
<p className="text-fg-4">~ Cade, Founder</p>
Expand Down
12 changes: 9 additions & 3 deletions app/(pages)/@modal/(layout)/subjects/[subjectId]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@ import * as Modal from '@/_components/modal';
import PageModalHeader from '@/_components/page-modal-header';
import SubjectForm from '@/_components/subject-form';
import getSubject from '@/_queries/get-subject';
import listTags from '@/_queries/list-tags';

interface PageProps {
params: Promise<{ subjectId: string }>;
}

const Page = async ({ params }: PageProps) => {
const { subjectId } = await params;
const { data: subject } = await getSubject(subjectId);
if (!subject) return null;

const [{ data: subject }, { data: tags }] = await Promise.all([
getSubject(subjectId),
listTags(),
]);

if (!subject || !tags) return null;

return (
<Modal.Content>
<PageModalHeader title="Edit subject" />
<SubjectForm subject={subject} />
<SubjectForm subject={subject} tags={tags} />
</Modal.Content>
);
};
Expand Down
18 changes: 12 additions & 6 deletions app/(pages)/@modal/(layout)/subjects/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import * as Modal from '@/_components/modal';
import PageModalHeader from '@/_components/page-modal-header';
import SubjectForm from '@/_components/subject-form';
import listTags from '@/_queries/list-tags';

const Page = () => (
<Modal.Content>
<PageModalHeader title="New subject" />
<SubjectForm />
</Modal.Content>
);
const Page = async () => {
const { data: tags } = await listTags();
if (!tags) return null;

return (
<Modal.Content>
<PageModalHeader title="New subject" />
<SubjectForm tags={tags} />
</Modal.Content>
);
};

export default Page;
2 changes: 1 addition & 1 deletion app/(pages)/@modal/(layout)/teams/[teamId]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const Page = async ({ params }: PageProps) => {

return (
<Modal.Content>
<PageModalHeader title="Edit team" />
<PageModalHeader title="Edit organization" />
<TeamForm team={team} />
</Modal.Content>
);
Expand Down
2 changes: 1 addition & 1 deletion app/(pages)/@modal/(layout)/teams/create/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import TeamForm from '@/_components/team-form';

const Page = async () => (
<Modal.Content>
<PageModalHeader title="New team" />
<PageModalHeader title="New organization" />
<TeamForm />
</Modal.Content>
);
Expand Down
2 changes: 1 addition & 1 deletion app/_components/account-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ const AccountMenu = ({ user, teams }: AccountMenuProps) => {
})}
<Drawer.Button href="/teams/create">
<PlusIcon className="w-5 text-fg-4" />
New team
New organization
</Drawer.Button>
<Drawer.Separator />
</>
Expand Down
2 changes: 1 addition & 1 deletion app/_components/avatar-dropzone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const AvatarDropzone = ({

return (
<div
className="group flex h-24 cursor-pointer items-center justify-center gap-6 rounded border-2 border-dashed border-alpha-2 px-4 text-fg-4 outline-none ring-accent-2 transition-colors focus:ring-1 group-hover:border-alpha-3"
className="group flex h-20 cursor-pointer items-center justify-center gap-6 rounded border-2 border-dashed border-alpha-2 px-4 text-fg-4 outline-none ring-accent-2 transition-colors focus:ring-1 group-hover:border-alpha-3"
{...dropzone.getRootProps()}
>
<Avatar file={file} id={avatarId} />
Expand Down
6 changes: 4 additions & 2 deletions app/_components/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
({ className, label, name, ...rest }, ref) => (
<div
className={twMerge(
'input relative flex items-center justify-between gap-4 pr-2',
'input relative flex items-center gap-2.5 pr-2 group-hover:bg-alpha-2',
className,
)}
>
Expand All @@ -23,6 +23,9 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
type="checkbox"
{...rest}
/>
<div className="relative -z-10 -ml-1.5 flex size-5 shrink-0 items-center justify-center rounded-full border border-alpha-1 bg-alpha-1 text-transparent transition-colors peer-checked:bg-accent-1 peer-checked:text-bg-1">
<CheckIcon className="w-4 stroke-2" />
</div>
<div
className={twMerge(
'text-fg-4 transition-colors peer-checked:text-fg-2',
Expand All @@ -31,7 +34,6 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
>
{label && <label htmlFor={name}>{label}</label>}
</div>
<CheckIcon className="relative -z-10 h-5 w-5 shrink-0 stroke-fg-2 opacity-0 transition-opacity peer-checked:opacity-100" />
</div>
),
);
Expand Down
2 changes: 1 addition & 1 deletion app/_components/drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const Content = React.forwardRef<
<DrawerPrimitive.Content
ref={ref}
className={twMerge(
'fixed inset-x-0 bottom-0 z-50 mt-24 h-auto w-full rounded-t border border-b-0 border-alpha-1 bg-bg-2',
'fixed inset-x-0 bottom-0 z-50 w-full rounded-t border border-b-0 border-alpha-1 bg-bg-2',
className,
)}
{...props}
Expand Down
28 changes: 5 additions & 23 deletions app/_components/event-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ import InputRoot from '@/_components/input-root';
import * as Label from '@/_components/label';
import * as Modal from '@/_components/modal';
import RichTextarea from '@/_components/rich-textarea';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import InputType from '@/_constants/enum-input-type';
import upsertEvent from '@/_mutations/upsert-event';
import { GetEventData } from '@/_queries/get-event';
import { GetEventTypeWithInputsAndOptionsData } from '@/_queries/get-event-type-with-inputs-and-options';
import { GetSessionWithDetailsData } from '@/_queries/get-session-with-details';
import DurationInputType from '@/_types/duration-input';
import { InputSettingsJson } from '@/_types/input-settings-json';
import MultiSelectInputType from '@/_types/multi-select-input-type';
import SelectInputType from '@/_types/select-input-type';
import forceArray from '@/_utilities/force-array';
import formatDatetimeLocal from '@/_utilities/format-datetime-local';
import parseSeconds from '@/_utilities/parse-seconds';
Expand Down Expand Up @@ -47,13 +45,7 @@ interface EventFormProps {
export interface EventFormValues {
comment: string;
completionTime: string;
inputs: Array<
| DurationInputType
| MultiSelectInputType
| SelectInputType
| boolean
| string
>;
inputs: Array<DurationInputType | string[] | string | boolean>;
}

const EventForm = ({
Expand Down Expand Up @@ -103,17 +95,11 @@ const EventForm = ({
}

case InputType.MultiSelect: {
return inputInputs.map(({ input_option_id }) =>
input.options.find(({ id }) => input_option_id === id),
);
return inputInputs.map(({ input_option_id }) => input_option_id);
}

case InputType.Select: {
return (
input.options.find(
({ id }) => id === inputInputs[0]?.input_option_id,
) ?? null
);
return inputInputs[0]?.input_option_id ?? null;
}
}
}) as EventFormValues['inputs'],
Expand Down Expand Up @@ -283,11 +269,7 @@ const EventForm = ({
control={form.control}
name={`inputs.${i}`}
render={({ field }) => (
<EventSelect
field={field}
id={`${eventType.id}-inputs-${i}`}
input={input}
/>
<EventSelect field={field} input={input} />
)}
/>
)}
Expand Down
69 changes: 22 additions & 47 deletions app/_components/event-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@
import { EventFormValues } from '@/_components/event-form';
import InputRoot from '@/_components/input-root';
import * as Label from '@/_components/label';
import Select, { IOption } from '@/_components/select';
import Select from '@/_components/select-v2';
import createInputOption from '@/_mutations/create-input-option';
import { Database } from '@/_types/database';
import { InputSettingsJson } from '@/_types/input-settings-json';
import { useRouter } from 'next/navigation';
import { useTransition } from 'react';
import { ControllerRenderProps } from 'react-hook-form';
import { PropsValue } from 'react-select';

interface EventSelectProps {
field: ControllerRenderProps<EventFormValues, `inputs.${number}`>;
id: string;
input: Pick<
Database['public']['Tables']['inputs']['Row'],
'id' | 'label' | 'settings' | 'type'
Expand All @@ -25,63 +22,41 @@ interface EventSelectProps {
};
}

const EventSelect = ({ field, id, input }: EventSelectProps) => {
const [isTransitioning, startTransition] = useTransition();

const optionOrOptions =
input.type === 'multi_select' ? 'options' : 'an option';

const EventSelect = ({ field, input }: EventSelectProps) => {
const inputSettings = input.settings as InputSettingsJson;

const placeholder = inputSettings?.isCreatable
? `Select ${optionOrOptions} or create your own…`
: `Select ${optionOrOptions}…`;

const router = useRouter();

return (
<InputRoot>
<Label.Root htmlFor={`react-select-${id}-input`}>
{input.label}
</Label.Root>
<Label.Root>{input.label}</Label.Root>
<Select
instanceId={id}
isCreatable={inputSettings?.isCreatable}
isLoading={isTransitioning}
isMulti={input.type === 'multi_select'}
isSearchable={inputSettings?.isCreatable}
onChange={field.onChange}
onCreateOption={(value: string) =>
startTransition(async () => {
const label = value.trim();
if (!label) return;

const { data, error } = await createInputOption({
inputId: input.id,
label,
});
onCreateOption={async (label: string) => {
const { data, error } = await createInputOption({
inputId: input.id,
label,
});

if (error) {
field.onChange(null);
alert(error);
return;
}
if (error) {
field.onChange(null);
alert(error);
return;
}

if (!data) return;
if (!data) return;

if (input.type === 'multi_select') {
(field.value as IOption[]).push(data);
field.onChange(field.value);
} else {
field.onChange(data);
}
if (input.type === 'multi_select') {
field.onChange([...(field.value as string[]), data.id]);
} else {
field.onChange(data.id);
}

router.refresh();
})
}
router.refresh();
}}
options={input.options}
placeholder={placeholder}
value={field.value as PropsValue<IOption>}
value={field.value as string | string[]}
/>
</InputRoot>
);
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-type-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as Label from '@/_components/label';
import * as Modal from '@/_components/modal';
import PageModalHeader from '@/_components/page-modal-header';
import RichTextarea from '@/_components/rich-textarea';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import UnsavedChangesBanner from '@/_components/unsaved-changes-banner';
import useCachedForm from '@/_hooks/use-cached-form';
import upsertEventType from '@/_mutations/upsert-event-type';
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-type-template-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as Label from '@/_components/label';
import * as Modal from '@/_components/modal';
import PageModalHeader from '@/_components/page-modal-header';
import RichTextarea from '@/_components/rich-textarea';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import TemplateFormSection from '@/_components/template-form-section';
import UnsavedChangesBanner from '@/_components/unsaved-changes-banner';
import useCachedForm from '@/_hooks/use-cached-form';
Expand Down
2 changes: 1 addition & 1 deletion app/_components/event-type-use-template-drawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import Button from '@/_components/button';
import * as Drawer from '@/_components/drawer';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import getTemplateData from '@/_queries/get-template-data';
import { ListInputsBySubjectIdData } from '@/_queries/list-inputs-by-subject-id';
import { ListTemplatesData } from '@/_queries/list-templates';
Expand Down
2 changes: 1 addition & 1 deletion app/_components/input-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Input from '@/_components/input';
import InputRoot from '@/_components/input-root';
import * as Label from '@/_components/label';
import * as Modal from '@/_components/modal';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import UnsavedChangesBanner from '@/_components/unsaved-changes-banner';
import INPUT_TYPE_LABELS from '@/_constants/constant-input-type-labels';
import InputType from '@/_constants/enum-input-type';
Expand Down
2 changes: 1 addition & 1 deletion app/_components/insight-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import InsightPlot from '@/_components/insight-plot';
import * as Label from '@/_components/label';
import * as Modal from '@/_components/modal';
import * as Popover from '@/_components/popover';
import Select, { IOption } from '@/_components/select';
import Select, { IOption } from '@/_components/select-v1';
import UnsavedChangesBanner from '@/_components/unsaved-changes-banner';
import ChartType from '@/_constants/enum-chart-type';
import Interval from '@/_constants/enum-interval';
Expand Down
Loading

0 comments on commit a7d2e33

Please sign in to comment.