Updated the permissions access
This commit is contained in:
@@ -1,14 +1,8 @@
|
||||
import React from "react";
|
||||
import { Permission } from "@/interfaces/permissions";
|
||||
import {
|
||||
createColumnHelper,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
Row,
|
||||
} from "@tanstack/react-table";
|
||||
import {Permission} from "@/interfaces/permissions";
|
||||
import {createColumnHelper, flexRender, getCoreRowModel, useReactTable, Row} from "@tanstack/react-table";
|
||||
import Link from "next/link";
|
||||
import { convertCamelCaseToReadable } from "@/utils/string";
|
||||
import {convertCamelCaseToReadable} from "@/utils/string";
|
||||
|
||||
interface Props {
|
||||
permissions: Permission[];
|
||||
@@ -19,28 +13,25 @@ const columnHelper = createColumnHelper<Permission>();
|
||||
const defaultColumns = [
|
||||
columnHelper.accessor("type", {
|
||||
header: () => <span>Type</span>,
|
||||
cell: ({ row, getValue }) => (
|
||||
cell: ({row, getValue}) => (
|
||||
<Link
|
||||
href={`/permissions/${row.original.id}`}
|
||||
key={row.id}
|
||||
className="underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer"
|
||||
>
|
||||
className="underline text-mti-purple-light hover:text-mti-purple-dark transition ease-in-out duration-300 cursor-pointer">
|
||||
{convertCamelCaseToReadable(getValue() as string)}
|
||||
</Link>
|
||||
),
|
||||
}),
|
||||
];
|
||||
|
||||
export default function PermissionList({ permissions }: Props) {
|
||||
export default function PermissionList({permissions}: Props) {
|
||||
const table = useReactTable({
|
||||
data: permissions,
|
||||
columns: defaultColumns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
});
|
||||
|
||||
const groupedData: { [key: string]: Row<Permission>[] } = table
|
||||
.getRowModel()
|
||||
.rows.reduce((groups: { [key: string]: Row<Permission>[] }, row) => {
|
||||
const groupedData: {[key: string]: Row<Permission>[]} = table.getRowModel().rows.reduce((groups: {[key: string]: Row<Permission>[]}, row) => {
|
||||
const parent = row.original.topic;
|
||||
if (!groups[parent]) {
|
||||
groups[parent] = [];
|
||||
@@ -50,7 +41,7 @@ export default function PermissionList({ permissions }: Props) {
|
||||
}, {});
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="w-full h-full">
|
||||
<div className="w-full flex flex-col gap-2">
|
||||
<table className="rounded-xl bg-mti-purple-ultralight/40 w-full">
|
||||
<thead>
|
||||
@@ -58,12 +49,7 @@ export default function PermissionList({ permissions }: Props) {
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => (
|
||||
<th className="py-4 px-4 text-left" key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
@@ -78,19 +64,10 @@ export default function PermissionList({ permissions }: Props) {
|
||||
</td>
|
||||
</tr>
|
||||
{groupedData[parent].map((row, i) => (
|
||||
<tr
|
||||
className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2"
|
||||
key={row.id}
|
||||
>
|
||||
<tr className="odd:bg-white even:bg-mti-purple-ultralight/40 rounded-lg py-2" key={row.id}>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<td
|
||||
className="px-4 py-2 items-center w-fit"
|
||||
key={cell.id}
|
||||
>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
<td className="px-4 py-2 items-center w-fit" key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
|
||||
@@ -316,7 +316,13 @@ export default function TeacherDashboard({user}: Props) {
|
||||
color="purple"
|
||||
/>
|
||||
{checkAccess(user, ["teacher", "developer"], permissions, "viewGroup") && (
|
||||
<IconCard Icon={BsPeople} label="Groups" value={groups.length} color="purple" onClick={() => setPage("groups")} />
|
||||
<IconCard
|
||||
Icon={BsPeople}
|
||||
label="Groups"
|
||||
value={groups.filter((x) => x.admin === user.id).length}
|
||||
color="purple"
|
||||
onClick={() => setPage("groups")}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
onClick={() => setPage("assignments")}
|
||||
|
||||
@@ -210,7 +210,6 @@ export default function GroupList({user}: {user: User}) {
|
||||
const {groups, reload} = useGroups({
|
||||
admin: user && filterTypes.includes(user?.type) ? user.id : undefined,
|
||||
userType: user?.type,
|
||||
adminAdmins: user?.type === "teacher" ? user?.id : undefined,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import Head from "next/head";
|
||||
import { withIronSessionSsr } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import {withIronSessionSsr} from "iron-session/next";
|
||||
import {sessionOptions} from "@/lib/session";
|
||||
import useUser from "@/hooks/useUser";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import {toast, ToastContainer} from "react-toastify";
|
||||
import Layout from "@/components/High/Layout";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { useState } from "react";
|
||||
import { Module } from "@/interfaces";
|
||||
import { RadioGroup, Tab } from "@headlessui/react";
|
||||
import {shouldRedirectHome} from "@/utils/navigation.disabled";
|
||||
import {useState} from "react";
|
||||
import {Module} from "@/interfaces";
|
||||
import {RadioGroup, Tab} from "@headlessui/react";
|
||||
import clsx from "clsx";
|
||||
import { MODULE_ARRAY } from "@/utils/moduleUtils";
|
||||
import { capitalize } from "lodash";
|
||||
import {MODULE_ARRAY} from "@/utils/moduleUtils";
|
||||
import {capitalize} from "lodash";
|
||||
import Button from "@/components/Low/Button";
|
||||
import { Exercise, ReadingPart } from "@/interfaces/exam";
|
||||
import {Exercise, ReadingPart} from "@/interfaces/exam";
|
||||
import Input from "@/components/Low/Input";
|
||||
import axios from "axios";
|
||||
import ReadingGeneration from "./(generation)/ReadingGeneration";
|
||||
@@ -21,9 +21,9 @@ import ListeningGeneration from "./(generation)/ListeningGeneration";
|
||||
import WritingGeneration from "./(generation)/WritingGeneration";
|
||||
import LevelGeneration from "./(generation)/LevelGeneration";
|
||||
import SpeakingGeneration from "./(generation)/SpeakingGeneration";
|
||||
import { checkAccess, getTypesOfUser } from "@/utils/permissions";
|
||||
import {checkAccess} from "@/utils/permissions";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
|
||||
export const getServerSideProps = withIronSessionSsr(({req, res}) => {
|
||||
const user = req.session.user;
|
||||
|
||||
if (!user || !user.isVerified) {
|
||||
@@ -35,10 +35,7 @@ export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
shouldRedirectHome(user) ||
|
||||
checkAccess(user, getTypesOfUser(["developer"]))
|
||||
) {
|
||||
if (shouldRedirectHome(user) || !checkAccess(user, ["admin", "mastercorporate", "developer", "corporate"])) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/",
|
||||
@@ -48,14 +45,14 @@ export const getServerSideProps = withIronSessionSsr(({ req, res }) => {
|
||||
}
|
||||
|
||||
return {
|
||||
props: { user: req.session.user },
|
||||
props: {user: req.session.user},
|
||||
};
|
||||
}, sessionOptions);
|
||||
|
||||
export default function Generation() {
|
||||
const [module, setModule] = useState<Module>("reading");
|
||||
|
||||
const { user } = useUser({ redirectTo: "/login" });
|
||||
const {user} = useUser({redirectTo: "/login"});
|
||||
|
||||
const [title, setTitle] = useState<string>("");
|
||||
return (
|
||||
@@ -85,17 +82,14 @@ export default function Generation() {
|
||||
required
|
||||
/>
|
||||
|
||||
<label className="font-normal text-base text-mti-gray-dim">
|
||||
Module
|
||||
</label>
|
||||
<label className="font-normal text-base text-mti-gray-dim">Module</label>
|
||||
<RadioGroup
|
||||
value={module}
|
||||
onChange={setModule}
|
||||
className="flex flex-row -2xl:flex-wrap w-full gap-4 -md:justify-center justify-between"
|
||||
>
|
||||
className="flex flex-row -2xl:flex-wrap w-full gap-4 -md:justify-center justify-between">
|
||||
{[...MODULE_ARRAY].map((x) => (
|
||||
<RadioGroup.Option value={x} key={x}>
|
||||
{({ checked }) => (
|
||||
{({checked}) => (
|
||||
<span
|
||||
className={clsx(
|
||||
"px-6 py-4 w-64 flex justify-center text-sm font-normal rounded-full border focus:outline-none cursor-pointer",
|
||||
@@ -119,9 +113,8 @@ export default function Generation() {
|
||||
x === "level" &&
|
||||
(!checked
|
||||
? "bg-white border-mti-gray-platinum"
|
||||
: "bg-ielts-level/70 border-ielts-level text-white")
|
||||
)}
|
||||
>
|
||||
: "bg-ielts-level/70 border-ielts-level text-white"),
|
||||
)}>
|
||||
{capitalize(x)}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import Head from "next/head";
|
||||
import { useState } from "react";
|
||||
import { withIronSessionSsr } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { Permission, PermissionType } from "@/interfaces/permissions";
|
||||
import { getPermissionDoc } from "@/utils/permissions.be";
|
||||
import { User } from "@/interfaces/user";
|
||||
import {useEffect, useState} from "react";
|
||||
import {withIronSessionSsr} from "iron-session/next";
|
||||
import {sessionOptions} from "@/lib/session";
|
||||
import {shouldRedirectHome} from "@/utils/navigation.disabled";
|
||||
import {Permission, PermissionType} from "@/interfaces/permissions";
|
||||
import {getPermissionDoc} from "@/utils/permissions.be";
|
||||
import {User} from "@/interfaces/user";
|
||||
import Layout from "@/components/High/Layout";
|
||||
import { getUsers } from "@/utils/users.be";
|
||||
import { BsTrash } from "react-icons/bs";
|
||||
import {getUsers} from "@/utils/users.be";
|
||||
import {BsTrash} from "react-icons/bs";
|
||||
import Select from "@/components/Low/Select";
|
||||
import Button from "@/components/Low/Button";
|
||||
import axios from "axios";
|
||||
import { toast, ToastContainer } from "react-toastify";
|
||||
import {Type as UserType} from '@/interfaces/user'
|
||||
import {toast, ToastContainer} from "react-toastify";
|
||||
import {Type as UserType} from "@/interfaces/user";
|
||||
import {getGroups} from "@/utils/groups.be";
|
||||
interface BasicUser {
|
||||
id: string;
|
||||
name: string;
|
||||
type: UserType
|
||||
type: UserType;
|
||||
}
|
||||
|
||||
interface PermissionWithBasicUsers {
|
||||
@@ -28,7 +29,7 @@ interface PermissionWithBasicUsers {
|
||||
}
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async (context) => {
|
||||
const { req, params } = context;
|
||||
const {req, params} = context;
|
||||
const user = req.session.user;
|
||||
|
||||
if (!user || !user.isVerified) {
|
||||
@@ -62,26 +63,34 @@ export const getServerSideProps = withIronSessionSsr(async (context) => {
|
||||
const permission: Permission = await getPermissionDoc(params.id as string);
|
||||
|
||||
const allUserData: User[] = await getUsers();
|
||||
const groups = await getGroups();
|
||||
|
||||
const userGroups = groups.filter((x) => x.admin === user.id);
|
||||
const filteredGroups =
|
||||
user.type === "corporate"
|
||||
? userGroups
|
||||
: user.type === "mastercorporate"
|
||||
? groups.filter((x) => userGroups.flatMap((y) => y.participants).includes(x.admin))
|
||||
: groups;
|
||||
|
||||
const users = allUserData.map((u) => ({
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
type: u.type
|
||||
type: u.type,
|
||||
})) as BasicUser[];
|
||||
|
||||
const filteredUsers = ["mastercorporate", "corporate"].includes(user.type)
|
||||
? users.filter((u) => filteredGroups.flatMap((g) => g.participants).includes(u.id))
|
||||
: users;
|
||||
|
||||
// const res = await fetch("api/permissions");
|
||||
// const permissions: Permission[] = await res.json();
|
||||
// Pass data to the page via props
|
||||
const usersData: BasicUser[] = permission.users.reduce(
|
||||
(acc: BasicUser[], userId) => {
|
||||
const user = users.find((u) => u.id === userId) as BasicUser;
|
||||
if (user) {
|
||||
acc.push(user);
|
||||
}
|
||||
const usersData: BasicUser[] = permission.users.reduce((acc: BasicUser[], userId) => {
|
||||
const user = filteredUsers.find((u) => u.id === userId) as BasicUser;
|
||||
if (!!user) acc.push(user);
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
}, []);
|
||||
|
||||
return {
|
||||
props: {
|
||||
@@ -92,7 +101,7 @@ export const getServerSideProps = withIronSessionSsr(async (context) => {
|
||||
users: usersData,
|
||||
},
|
||||
user: req.session.user,
|
||||
users,
|
||||
users: filteredUsers,
|
||||
},
|
||||
};
|
||||
}, sessionOptions);
|
||||
@@ -104,15 +113,11 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function Page(props: Props) {
|
||||
const { permission, user, users } = props;
|
||||
const {permission, user, users} = props;
|
||||
|
||||
|
||||
const [selectedUsers, setSelectedUsers] = useState<string[]>(() =>
|
||||
permission.users.map((u) => u.id)
|
||||
);
|
||||
const [selectedUsers, setSelectedUsers] = useState<string[]>(() => permission.users.map((u) => u.id));
|
||||
|
||||
const onChange = (value: any) => {
|
||||
|
||||
setSelectedUsers((prev) => {
|
||||
if (value?.value) {
|
||||
return [...prev, value?.value];
|
||||
@@ -125,7 +130,6 @@ export default function Page(props: Props) {
|
||||
};
|
||||
|
||||
const update = async () => {
|
||||
|
||||
try {
|
||||
await axios.patch(`/api/permissions/${permission.id}`, {
|
||||
users: selectedUsers,
|
||||
@@ -149,9 +153,8 @@ export default function Page(props: Props) {
|
||||
</Head>
|
||||
<ToastContainer />
|
||||
<Layout user={user} className="gap-6">
|
||||
<h1 className="text-2xl font-semibold">
|
||||
Permission: {permission.type as string}
|
||||
</h1>
|
||||
<div className="flex flex-col gap-6 w-full h-[88vh] overflow-y-scroll scrollbar-hide rounded-xl">
|
||||
<h1 className="text-2xl font-semibold">Permission: {permission.type as string}</h1>
|
||||
<div className="flex gap-3">
|
||||
<Select
|
||||
value={null}
|
||||
@@ -172,16 +175,11 @@ export default function Page(props: Props) {
|
||||
{selectedUsers.map((userId) => {
|
||||
const user = users.find((u) => u.id === userId);
|
||||
return (
|
||||
<div
|
||||
className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4"
|
||||
key={userId}
|
||||
>
|
||||
<span className="text-base first-letter:uppercase">{user?.type}-{user?.name}</span>
|
||||
<BsTrash
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => removeUser(userId)}
|
||||
size={20}
|
||||
/>
|
||||
<div className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4" key={userId}>
|
||||
<span className="text-base first-letter:uppercase">
|
||||
{user?.type}-{user?.name}
|
||||
</span>
|
||||
<BsTrash style={{cursor: "pointer"}} onClick={() => removeUser(userId)} size={20} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -190,19 +188,21 @@ export default function Page(props: Props) {
|
||||
<div className="flex flex-col gap-3">
|
||||
<h2>Whitelisted Users</h2>
|
||||
<div className="flex flex-col gap-3 flex-wrap">
|
||||
{users.filter(user => !selectedUsers.includes(user.id)).map((user) => {
|
||||
{users
|
||||
.filter((user) => !selectedUsers.includes(user.id))
|
||||
.map((user) => {
|
||||
return (
|
||||
<div
|
||||
className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4"
|
||||
key={user.id}
|
||||
>
|
||||
<span className="text-base first-letter:uppercase">{user?.type}-{user?.name}</span>
|
||||
<div className="flex p-4 rounded-xl w-auto bg-mti-purple-light text-white gap-4" key={user.id}>
|
||||
<span className="text-base first-letter:uppercase">
|
||||
{user?.type}-{user?.name}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import Head from "next/head";
|
||||
import { withIronSessionSsr } from "iron-session/next";
|
||||
import { sessionOptions } from "@/lib/session";
|
||||
import { shouldRedirectHome } from "@/utils/navigation.disabled";
|
||||
import { Permission } from "@/interfaces/permissions";
|
||||
import { getPermissionDocs } from "@/utils/permissions.be";
|
||||
import { User } from "@/interfaces/user";
|
||||
import {withIronSessionSsr} from "iron-session/next";
|
||||
import {sessionOptions} from "@/lib/session";
|
||||
import {shouldRedirectHome} from "@/utils/navigation.disabled";
|
||||
import {Permission} from "@/interfaces/permissions";
|
||||
import {getPermissionDocs} from "@/utils/permissions.be";
|
||||
import {User} from "@/interfaces/user";
|
||||
import Layout from "@/components/High/Layout";
|
||||
import PermissionList from '@/components/PermissionList'
|
||||
import PermissionList from "@/components/PermissionList";
|
||||
|
||||
export const getServerSideProps = withIronSessionSsr(async ({ req }) => {
|
||||
export const getServerSideProps = withIronSessionSsr(async ({req}) => {
|
||||
const user = req.session.user;
|
||||
|
||||
if (!user || !user.isVerified) {
|
||||
@@ -32,7 +32,14 @@ export const getServerSideProps = withIronSessionSsr(async ({ req }) => {
|
||||
|
||||
// Fetch data from external API
|
||||
const permissions: Permission[] = await getPermissionDocs();
|
||||
const filteredPermissions = permissions.filter((p) => {
|
||||
const permissionType = p.type.toString().toLowerCase();
|
||||
|
||||
if (user.type === "corporate") return !permissionType.includes("corporate") && !permissionType.includes("admin");
|
||||
if (user.type === "mastercorporate") return !permissionType.includes("mastercorporate") && !permissionType.includes("admin");
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// const res = await fetch("api/permissions");
|
||||
// const permissions: Permission[] = await res.json();
|
||||
@@ -40,8 +47,8 @@ export const getServerSideProps = withIronSessionSsr(async ({ req }) => {
|
||||
return {
|
||||
props: {
|
||||
// permissions: permissions.map((p) => ({ id: p.id, type: p.type })),
|
||||
permissions: permissions.map((p) => {
|
||||
const { users, ...rest } = p;
|
||||
permissions: filteredPermissions.map((p) => {
|
||||
const {users, ...rest} = p;
|
||||
return rest;
|
||||
}),
|
||||
user: req.session.user,
|
||||
@@ -55,7 +62,8 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function Page(props: Props) {
|
||||
const { permissions, user } = props;
|
||||
const {permissions, user} = props;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -69,7 +77,7 @@ export default function Page(props: Props) {
|
||||
</Head>
|
||||
<Layout user={user} className="gap-6">
|
||||
<h1 className="text-2xl font-semibold">Permissions</h1>
|
||||
<div className="flex gap-3 flex-wrap">
|
||||
<div className="flex gap-3 flex-wrap overflow-y-scroll scrollbar-hide h-[80vh] rounded-xl">
|
||||
<PermissionList permissions={permissions} />
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -2,3 +2,89 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer utilities {
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none;
|
||||
/* IE and Edge */
|
||||
scrollbar-width: none;
|
||||
/* Firefox */
|
||||
}
|
||||
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none;
|
||||
/* Chrome, Safari and Opera */
|
||||
}
|
||||
}
|
||||
|
||||
.training-scrollbar::-webkit-scrollbar {
|
||||
@apply w-1.5;
|
||||
}
|
||||
|
||||
.training-scrollbar::-webkit-scrollbar-track {
|
||||
@apply bg-transparent;
|
||||
}
|
||||
|
||||
.training-scrollbar::-webkit-scrollbar-thumb {
|
||||
@apply bg-gray-400 hover:bg-gray-500 rounded-full transition-colors opacity-50 hover:opacity-75;
|
||||
}
|
||||
|
||||
.training-scrollbar {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
|
||||
}
|
||||
|
||||
:root {
|
||||
--max-width: 1100px;
|
||||
--border-radius: 12px;
|
||||
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
|
||||
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
|
||||
|
||||
--foreground-rgb: 53, 51, 56;
|
||||
--background-start-rgb: 245, 245, 245;
|
||||
--background-end-rgb: 245, 245, 245;
|
||||
|
||||
--primary-glow: conic-gradient(from 180deg at 50% 50%, #16abff33 0deg, #0885ff33 55deg, #54d6ff33 120deg, #0071ff33 160deg, transparent 360deg);
|
||||
--secondary-glow: radial-gradient(rgba(255, 255, 255, 1), rgba(255, 255, 255, 0));
|
||||
|
||||
--tile-start-rgb: 239, 245, 249;
|
||||
--tile-end-rgb: 228, 232, 233;
|
||||
--tile-border: conic-gradient(#00000080, #00000040, #00000030, #00000020, #00000010, #00000010, #00000080);
|
||||
|
||||
--callout-rgb: 238, 240, 241;
|
||||
--callout-border-rgb: 172, 175, 176;
|
||||
--card-rgb: 180, 185, 188;
|
||||
--card-border-rgb: 131, 134, 135;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100vh !important;
|
||||
height: 100%;
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
font-family: "Open Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh !important;
|
||||
height: 100%;
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
font-family: "Open Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(to bottom, transparent, rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,11 @@ export const updateExpiryDateOnGroup = async (participantID: string, corporateID
|
||||
return;
|
||||
};
|
||||
|
||||
export const getGroups = async () => {
|
||||
const groupDocs = await getDocs(collection(db, "groups"));
|
||||
return groupDocs.docs.map((x) => ({...x.data(), id: x.id})) as Group[];
|
||||
};
|
||||
|
||||
export const getUserGroups = async (id: string): Promise<Group[]> => {
|
||||
const groupDocs = await getDocs(query(collection(db, "groups"), where("admin", "==", id)));
|
||||
return groupDocs.docs.map((x) => ({...x.data(), id})) as Group[];
|
||||
|
||||
Reference in New Issue
Block a user