fix ux
This commit is contained in:
parent
d4cd046c4b
commit
3d89632047
@ -13,7 +13,7 @@ const AdminBarLayout = ({
|
|||||||
return (
|
return (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
{data?.user.role === Role.ADMIN ? (
|
{data?.user.role === Role.ADMIN ? (
|
||||||
<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">
|
<div className="sticky left-0 right-0 top-2 z-10 mx-auto mb-3 mt-4 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">
|
<h1 className="rounded-lg px-4 py-2 font-semibold text-black">
|
||||||
Admin Mode
|
Admin Mode
|
||||||
</h1>
|
</h1>
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { PaymentType, type AuditoryResource, SkillLevel } from "@prisma/client";
|
import {
|
||||||
|
PaymentType,
|
||||||
|
type AuditoryResource,
|
||||||
|
SkillLevel,
|
||||||
|
Skill,
|
||||||
|
} from "@prisma/client";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { PencilSquareIcon } from "@heroicons/react/24/solid";
|
import { PencilSquareIcon } from "@heroicons/react/24/solid";
|
||||||
import {
|
import {
|
||||||
MultiSelector,
|
MultiSelector,
|
||||||
MultiSelectorMany,
|
MultiSelectorMany,
|
||||||
MultiSelectorOption,
|
MultiSelectorOption,
|
||||||
SelectedManyContext,
|
|
||||||
SelectedUniqueContext,
|
SelectedUniqueContext,
|
||||||
|
SimpleSelectorManyOption,
|
||||||
} from "../../forms/selectors";
|
} from "../../forms/selectors";
|
||||||
import { InfoInputLine } from "~/components/forms/textInput";
|
import { InfoInputLine } from "~/components/forms/textInput";
|
||||||
import { PriceIcon } from "~/prices/Icons";
|
import { PriceIcon } from "~/prices/Icons";
|
||||||
@ -51,8 +56,8 @@ const SelectImageInput = ({ file }: { file?: string }) => {
|
|||||||
const ResourceLinkSubForm = ({}) => {
|
const ResourceLinkSubForm = ({}) => {
|
||||||
return (
|
return (
|
||||||
<div className="mx-4">
|
<div className="mx-4">
|
||||||
<h1 className="mb-2 border-b border-neutral-400">Links</h1>
|
<h1 className="mb-2 border-b border-neutral-400 text-xl">Links</h1>
|
||||||
<div className="flex mx-auto w-48 flex-col space-y-2">
|
<div className="mx-auto flex w-48 flex-col space-y-2">
|
||||||
{/** Insert existing links here */}
|
{/** Insert existing links here */}
|
||||||
<button type="button">
|
<button type="button">
|
||||||
<div className="flex h-14 flex-row space-x-2 rounded-lg border-2 border-neutral-900 bg-amber-300 px-2 align-middle hover:bg-amber-200">
|
<div className="flex h-14 flex-row space-x-2 rounded-lg border-2 border-neutral-900 bg-amber-300 px-2 align-middle hover:bg-amber-200">
|
||||||
@ -99,42 +104,6 @@ const PaymentTypeOption = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resource summary inputs - ie description, manufacturer, etc.
|
* Resource summary inputs - ie description, manufacturer, etc.
|
||||||
*/
|
*/
|
||||||
@ -145,11 +114,14 @@ const ResourceSummarySubForm = ({
|
|||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4 px-4">
|
<div className="space-y-4 px-4">
|
||||||
<div className="flex flex-row space-x-4 pt-4">
|
<div className="flex flex-row space-x-4 sm:mt-4">
|
||||||
<div className="flex w-20 flex-col justify-center space-y-2 sm:w-28">
|
<div className="flex w-20 flex-col justify-center space-y-2 sm:w-28">
|
||||||
<SelectImageInput file={resource?.icon} />
|
<SelectImageInput file={resource?.icon} />
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full overflow-hidden rounded-xl border border-neutral-400 bg-white drop-shadow-lg">
|
<div className="flex flex-col justify-center overflow-hidden rounded-xl border border-neutral-400 bg-white drop-shadow-lg sm:w-[300px] md:w-[400px]">
|
||||||
|
<h2 className="border-b border-neutral-300 px-2 text-center font-semibold">
|
||||||
|
Resource Details
|
||||||
|
</h2>
|
||||||
<span className="text-md">
|
<span className="text-md">
|
||||||
<InfoInputLine
|
<InfoInputLine
|
||||||
placeholder="manufacturer"
|
placeholder="manufacturer"
|
||||||
@ -188,9 +160,30 @@ const ResourceSummarySubForm = ({
|
|||||||
label="Skill Level"
|
label="Skill Level"
|
||||||
defaultValues={resource?.skill_levels ?? []}
|
defaultValues={resource?.skill_levels ?? []}
|
||||||
>
|
>
|
||||||
<SkillLevelOption type={SkillLevel.BEGINNER} label="beginner" />
|
{Object.values(SkillLevel).map((skillLevel, index) => {
|
||||||
<SkillLevelOption type={SkillLevel.INTERMEDIATE} label="intermediate" />
|
return (
|
||||||
<SkillLevelOption type={SkillLevel.ADVANCED} label="advanced" />
|
<SimpleSelectorManyOption
|
||||||
|
key={index}
|
||||||
|
type={skillLevel}
|
||||||
|
label={skillLevel.toLowerCase()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</MultiSelectorMany>
|
||||||
|
|
||||||
|
<MultiSelectorMany
|
||||||
|
label="Skills Covered"
|
||||||
|
defaultValues={resource?.skills ?? []}
|
||||||
|
>
|
||||||
|
{Object.values(Skill).map((skill, index) => {
|
||||||
|
return (
|
||||||
|
<SimpleSelectorManyOption
|
||||||
|
key={index}
|
||||||
|
type={skill}
|
||||||
|
label={skill.toLowerCase()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</MultiSelectorMany>
|
</MultiSelectorMany>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -207,12 +200,17 @@ const ResourceSummarySubForm = ({
|
|||||||
|
|
||||||
const ResourceForm = ({ resource }: { resource?: AuditoryResource }) => {
|
const ResourceForm = ({ resource }: { resource?: AuditoryResource }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex mx-auto max-w-2xl flex-col flex-col-reverse py-1 sm:flex-row sm:divide-x sm:py-4">
|
<div className="mx-auto flex max-w-2xl flex-col flex-col-reverse py-1 sm:flex-row sm:divide-x sm:py-4">
|
||||||
<div className="flex my-5 mr-4 flex-col justify-end text-lg font-bold">
|
<div className="my-5 mr-4 flex flex-col justify-end text-lg font-bold">
|
||||||
<ResourceLinkSubForm /> {/** //resource={resource} /> */}
|
<ResourceLinkSubForm /> {/** //resource={resource} /> */}
|
||||||
</div>
|
</div>
|
||||||
<div className="justify-left flex mx-auto max-w-lg flex-col pb-5">
|
<div>
|
||||||
<ResourceSummarySubForm resource={resource} />
|
<h1 className="mx-4 mb-2 border-b border-neutral-400 text-xl font-bold sm:hidden">
|
||||||
|
General
|
||||||
|
</h1>
|
||||||
|
<div className="justify-left mx-auto flex max-w-lg flex-col pb-5">
|
||||||
|
<ResourceSummarySubForm resource={resource} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { createContext, useContext, useState } from "react";
|
import { createContext, useContext, useState } from "react";
|
||||||
|
|
||||||
|
// generics
|
||||||
|
interface ToStringable {
|
||||||
|
toString: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
// Define contexts
|
// Define contexts
|
||||||
const SelectorContext = createContext<{
|
const SelectorContext = createContext<{
|
||||||
type: "one" | "many";
|
type: "one" | "many";
|
||||||
@ -13,7 +18,7 @@ const SelectorContext = createContext<{
|
|||||||
const SelectedUniqueContext = createContext<string>("");
|
const SelectedUniqueContext = createContext<string>("");
|
||||||
const SelectedManyContext = createContext<string[]>([]);
|
const SelectedManyContext = createContext<string[]>([]);
|
||||||
|
|
||||||
function MultiSelectorMany<T extends { toString: () => string }>({
|
function MultiSelectorMany<T extends ToStringable>({
|
||||||
label,
|
label,
|
||||||
defaultValues,
|
defaultValues,
|
||||||
children,
|
children,
|
||||||
@ -55,7 +60,7 @@ function MultiSelectorMany<T extends { toString: () => string }>({
|
|||||||
className="hidden"
|
className="hidden"
|
||||||
value={selected ?? ""}
|
value={selected ?? ""}
|
||||||
/>
|
/>
|
||||||
<div className="flex mt-2 flex-row space-x-2 overflow-x-auto">
|
<div className="mt-2 space-x-2 space-y-2 overflow-x-auto">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -64,7 +69,7 @@ function MultiSelectorMany<T extends { toString: () => string }>({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MultiSelector<T extends { toString: () => string }>({
|
function MultiSelector<T extends ToStringable>({
|
||||||
label,
|
label,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
children,
|
children,
|
||||||
@ -77,7 +82,7 @@ function MultiSelector<T extends { toString: () => string }>({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectorContext.Provider
|
<SelectorContext.Provider
|
||||||
value={{ type: "many", updateCallback: setSelected }}
|
value={{ type: "one", updateCallback: setSelected }}
|
||||||
>
|
>
|
||||||
<SelectedUniqueContext.Provider value={selected}>
|
<SelectedUniqueContext.Provider value={selected}>
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
@ -91,16 +96,14 @@ function MultiSelector<T extends { toString: () => string }>({
|
|||||||
className="hidden"
|
className="hidden"
|
||||||
value={selected ?? ""}
|
value={selected ?? ""}
|
||||||
/>
|
/>
|
||||||
<div className="flex mt-2 flex-row space-x-2 overflow-x-auto">
|
<div className="space-x-2 space-y-2 overflow-x-auto">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</SelectedUniqueContext.Provider>
|
</SelectedUniqueContext.Provider>
|
||||||
</SelectorContext.Provider>
|
</SelectorContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function MultiSelectorOption<T extends { toString: () => string }>({
|
function MultiSelectorOption<T extends ToStringable>({
|
||||||
value,
|
value,
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
@ -121,6 +124,42 @@ function MultiSelectorOption<T extends { toString: () => string }>({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function SimpleSelectorManyOption<T extends ToStringable>({
|
||||||
|
type,
|
||||||
|
label,
|
||||||
|
}: {
|
||||||
|
type: T;
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
SelectedUniqueContext,
|
SelectedUniqueContext,
|
||||||
SelectorContext,
|
SelectorContext,
|
||||||
@ -128,4 +167,5 @@ export {
|
|||||||
MultiSelectorMany,
|
MultiSelectorMany,
|
||||||
MultiSelector,
|
MultiSelector,
|
||||||
MultiSelectorOption,
|
MultiSelectorOption,
|
||||||
|
SimpleSelectorManyOption,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user