add skill level selector
This commit is contained in:
parent
8810e03894
commit
d4cd046c4b
@ -13,7 +13,7 @@ const AdminBarLayout = ({
|
||||
return (
|
||||
<div className="relative">
|
||||
{data?.user.role === Role.ADMIN ? (
|
||||
<div className="flex sticky left-0 right-0 top-[71px] z-10 mx-auto mb-3 mt-[15px] max-w-4xl flex-row justify-between rounded-xl border border-neutral-600 bg-red-300 drop-shadow-xl sm:mb-6">
|
||||
<div className="sticky left-0 right-0 top-[71px] z-10 mx-auto mb-3 mt-[15px] flex max-w-4xl flex-row justify-between rounded-xl border border-neutral-600 bg-red-300 drop-shadow-xl sm:mb-6">
|
||||
<h1 className="rounded-lg px-4 py-2 font-semibold text-black">
|
||||
Admin Mode
|
||||
</h1>
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { PaymentType, type AuditoryResource } from "@prisma/client";
|
||||
import { PaymentType, type AuditoryResource, SkillLevel } from "@prisma/client";
|
||||
import Image from "next/image";
|
||||
import { PencilSquareIcon } from "@heroicons/react/24/solid";
|
||||
import {
|
||||
MultiSelector,
|
||||
MultiSelectorContext,
|
||||
MultiSelectorMany,
|
||||
MultiSelectorOption,
|
||||
SelectedManyContext,
|
||||
SelectedUniqueContext,
|
||||
} from "../../forms/selectors";
|
||||
import { InfoInputLine } from "~/components/forms/textInput";
|
||||
import { PriceIcon } from "~/prices/Icons";
|
||||
@ -71,8 +73,8 @@ const PaymentTypeOption = ({
|
||||
}) => {
|
||||
return (
|
||||
<MultiSelectorOption value={type}>
|
||||
<MultiSelectorContext.Consumer>
|
||||
{({ selected }) => (
|
||||
<SelectedUniqueContext.Consumer>
|
||||
{(selected) => (
|
||||
<div
|
||||
className={
|
||||
(selected === type ? "bg-stone-800" : "bg-white") +
|
||||
@ -92,7 +94,43 @@ const PaymentTypeOption = ({
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</MultiSelectorContext.Consumer>
|
||||
</SelectedUniqueContext.Consumer>
|
||||
</MultiSelectorOption>
|
||||
);
|
||||
};
|
||||
|
||||
const SkillLevelOption = ({
|
||||
type,
|
||||
label,
|
||||
}: {
|
||||
type: SkillLevel;
|
||||
label: string;
|
||||
}) => {
|
||||
return (
|
||||
<MultiSelectorOption value={type}>
|
||||
<SelectedManyContext.Consumer>
|
||||
{(selected) => (
|
||||
<div
|
||||
className={
|
||||
(selected.includes(type.toString())
|
||||
? "bg-stone-800"
|
||||
: "bg-white") +
|
||||
" flex flex-row space-x-2 whitespace-nowrap rounded-xl border border-neutral-400 px-2 py-1"
|
||||
}
|
||||
>
|
||||
<span
|
||||
className={
|
||||
(selected.includes(type.toString())
|
||||
? "text-white"
|
||||
: "text black") +
|
||||
" my-auto inline-block whitespace-nowrap text-sm"
|
||||
}
|
||||
>
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</SelectedManyContext.Consumer>
|
||||
</MultiSelectorOption>
|
||||
);
|
||||
};
|
||||
@ -129,24 +167,31 @@ const ResourceSummarySubForm = ({
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<MultiSelector
|
||||
label="Price Category"
|
||||
defaultValue={
|
||||
resource?.payment_options.toString() ?? PaymentType.FREE.toString()
|
||||
}
|
||||
>
|
||||
<PaymentTypeOption type={PaymentType.FREE} label="Free" />
|
||||
<PaymentTypeOption
|
||||
type={PaymentType.SUBSCRIPTION_MONTHLY}
|
||||
label="Monthly Subscription"
|
||||
/>
|
||||
<PaymentTypeOption
|
||||
type={PaymentType.SUBSCRIPTION_WEEKLY}
|
||||
label="Weekly Subscription"
|
||||
/>
|
||||
</MultiSelector>
|
||||
</div>
|
||||
<MultiSelector
|
||||
label="Price Category"
|
||||
defaultValue={
|
||||
resource?.payment_options.toString() ?? PaymentType.FREE.toString()
|
||||
}
|
||||
>
|
||||
<PaymentTypeOption type={PaymentType.FREE} label="Free" />
|
||||
<PaymentTypeOption
|
||||
type={PaymentType.SUBSCRIPTION_MONTHLY}
|
||||
label="Monthly Subscription"
|
||||
/>
|
||||
<PaymentTypeOption
|
||||
type={PaymentType.SUBSCRIPTION_WEEKLY}
|
||||
label="Weekly Subscription"
|
||||
/>
|
||||
</MultiSelector>
|
||||
|
||||
<MultiSelectorMany
|
||||
label="Skill Level"
|
||||
defaultValues={resource?.skill_levels ?? []}
|
||||
>
|
||||
<SkillLevelOption type={SkillLevel.BEGINNER} label="beginner" />
|
||||
<SkillLevelOption type={SkillLevel.INTERMEDIATE} label="intermediate" />
|
||||
<SkillLevelOption type={SkillLevel.ADVANCED} label="advanced" />
|
||||
</MultiSelectorMany>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,12 +1,68 @@
|
||||
import { createContext, useContext, useState } from "react";
|
||||
|
||||
// Define contexts
|
||||
const MultiSelectorContext = createContext({
|
||||
selected: "",
|
||||
const SelectorContext = createContext<{
|
||||
type: "one" | "many";
|
||||
updateCallback: (_value: string) => void;
|
||||
}>({
|
||||
type: "one",
|
||||
updateCallback: (_value: string) => {
|
||||
return;
|
||||
},
|
||||
});
|
||||
const SelectedUniqueContext = createContext<string>("");
|
||||
const SelectedManyContext = createContext<string[]>([]);
|
||||
|
||||
function MultiSelectorMany<T extends { toString: () => string }>({
|
||||
label,
|
||||
defaultValues,
|
||||
children,
|
||||
}: {
|
||||
label: string;
|
||||
defaultValues: T[];
|
||||
children: undefined | JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
const [selected, setSelected] = useState<string[]>(
|
||||
defaultValues.map((value) => {
|
||||
return value.toString();
|
||||
})
|
||||
);
|
||||
|
||||
const updateCallback = (value: string) => {
|
||||
if (selected.includes(value)) {
|
||||
setSelected(
|
||||
selected.filter((selectedValue) => {
|
||||
return selectedValue !== value;
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
setSelected([value, ...selected]);
|
||||
};
|
||||
|
||||
return (
|
||||
<SelectorContext.Provider value={{ type: "many", updateCallback }}>
|
||||
<SelectedManyContext.Provider value={selected}>
|
||||
<div className="flex flex-col">
|
||||
<label className="text-md block font-semibold">{label}</label>
|
||||
<span className="block text-sm italic text-neutral-400">
|
||||
Select all that apply
|
||||
</span>
|
||||
<input
|
||||
readOnly
|
||||
type="text"
|
||||
className="hidden"
|
||||
value={selected ?? ""}
|
||||
/>
|
||||
<div className="flex mt-2 flex-row space-x-2 overflow-x-auto">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</SelectedManyContext.Provider>
|
||||
</SelectorContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function MultiSelector<T extends { toString: () => string }>({
|
||||
label,
|
||||
@ -20,20 +76,27 @@ function MultiSelector<T extends { toString: () => string }>({
|
||||
const [selected, setSelected] = useState<string>(defaultValue.toString());
|
||||
|
||||
return (
|
||||
<MultiSelectorContext.Provider
|
||||
value={{ selected, updateCallback: setSelected }}
|
||||
<SelectorContext.Provider
|
||||
value={{ type: "many", updateCallback: setSelected }}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<label className="text-md block font-semibold">{label}</label>
|
||||
<span className="block text-sm italic text-neutral-400">
|
||||
Select one from below
|
||||
</span>
|
||||
<input readOnly type="text" className="hidden" value={selected ?? ""} />
|
||||
<div className="mt-2 flex flex-row space-x-2 overflow-x-auto">
|
||||
{children}
|
||||
<SelectedUniqueContext.Provider value={selected}>
|
||||
<div className="flex flex-col">
|
||||
<label className="text-md block font-semibold">{label}</label>
|
||||
<span className="block text-sm italic text-neutral-400">
|
||||
Select one from below
|
||||
</span>
|
||||
<input
|
||||
readOnly
|
||||
type="text"
|
||||
className="hidden"
|
||||
value={selected ?? ""}
|
||||
/>
|
||||
<div className="flex mt-2 flex-row space-x-2 overflow-x-auto">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MultiSelectorContext.Provider>
|
||||
</SelectedUniqueContext.Provider>
|
||||
</SelectorContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -44,7 +107,7 @@ function MultiSelectorOption<T extends { toString: () => string }>({
|
||||
value: T;
|
||||
children: undefined | JSX.Element | JSX.Element[];
|
||||
}) {
|
||||
const { updateCallback } = useContext(MultiSelectorContext);
|
||||
const { updateCallback } = useContext(SelectorContext);
|
||||
|
||||
return (
|
||||
<button
|
||||
@ -58,4 +121,11 @@ function MultiSelectorOption<T extends { toString: () => string }>({
|
||||
);
|
||||
}
|
||||
|
||||
export { MultiSelectorContext, MultiSelector, MultiSelectorOption };
|
||||
export {
|
||||
SelectedUniqueContext,
|
||||
SelectorContext,
|
||||
SelectedManyContext,
|
||||
MultiSelectorMany,
|
||||
MultiSelector,
|
||||
MultiSelectorOption,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user