,
5 | callback: () => void
6 | ): void => {
7 | const handleClick = (e: MouseEvent) => {
8 | if (ref.current && !ref.current.contains(e.target as Node)) {
9 | callback();
10 | }
11 | };
12 |
13 | useEffect(() => {
14 | document.addEventListener("click", handleClick);
15 | return () => {
16 | document.removeEventListener("click", handleClick);
17 | };
18 | }, [ref, callback]);
19 | };
20 |
--------------------------------------------------------------------------------
/apps/web/hooks/useRoles.ts:
--------------------------------------------------------------------------------
1 | import { useAuth } from "./useAuth";
2 |
3 | const Properties = {
4 | admin: {
5 | canDeleteOrg: true,
6 | canSendInvite: true,
7 | canCreateEvent: true,
8 | canEditEvent: true,
9 | canRemoveOrgUser: true,
10 | canViewDashboard: true,
11 | canChangeParticipantStatus: true,
12 | canSeeRevenue: true,
13 | canDeleteEvent: true,
14 | canEditOrg: true,
15 | },
16 | editor: {
17 | canDeleteOrg: false,
18 | canEditEvent: true,
19 | canCreateEvent: true,
20 | canViewDashboard: true,
21 | canSendInvite: false,
22 | canRemoveOrgUser: false,
23 | canChangeParticipantStatus: true,
24 | canSeeRevenue: false,
25 | canDeleteEvent: false,
26 | canEditOrg: false,
27 | },
28 | viewer: {
29 | canDeleteOrg: false,
30 | canEditEvent: false,
31 | canCreateEvent: false,
32 | canSendInvite: false,
33 | canRemoveOrgUser: false,
34 | canViewDashboard: true,
35 | canChangeParticipantStatus: true,
36 | canSeeRevenue: false,
37 | canDeleteEvent: false,
38 | canEditOrg: false,
39 | },
40 | no_access: {
41 | canDeleteOrg: false,
42 | canEditEvent: false,
43 | canCreateEvent: false,
44 | canSendInvite: false,
45 | canRemoveOrgUser: false,
46 | canViewDashboard: true,
47 | canChangeParticipantStatus: false,
48 | canSeeRevenue: false,
49 | canDeleteEvent: false,
50 | canEditOrg: false,
51 | },
52 | };
53 |
54 | export const useRoles = () => {
55 | const { role } = useAuth();
56 |
57 | if (!role) {
58 | return Properties["no_access"];
59 | }
60 | return Properties[role];
61 | };
62 |
--------------------------------------------------------------------------------
/apps/web/hooks/useToggle.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from "react";
2 |
3 | type VoidFn = () => void;
4 |
5 | export type Toggle = {
6 | on: VoidFn;
7 | off: VoidFn;
8 | toggle: VoidFn;
9 | };
10 |
11 | type UseToggleReturn = [boolean, Toggle];
12 |
13 | export const useToggle = (initialState = false): UseToggleReturn => {
14 | const [value, setValue] = useState(initialState);
15 |
16 | const on = useCallback(() => {
17 | setValue(true);
18 | }, []);
19 |
20 | const off = useCallback(() => {
21 | setValue(false);
22 | }, []);
23 |
24 | const toggle = useCallback((isOpen?: boolean) => {
25 | setValue((prev) => (typeof isOpen === "boolean" ? isOpen : !prev));
26 | }, []);
27 |
28 | return [value, { on, off, toggle }];
29 | };
30 |
--------------------------------------------------------------------------------
/apps/web/layout/AuthModal.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import { Button } from "@app/ui/components/button";
3 | import {
4 | Dialog,
5 | DialogContent,
6 | DialogDescription,
7 | DialogHeader,
8 | DialogTitle,
9 | } from "@app/ui/components/dialog";
10 | import { ENV } from "@app/config";
11 | import { useAuth } from "@app/hooks";
12 |
13 | export const AuthModal = () => {
14 | const router = useRouter();
15 | const { isAuthModalOpen, toggleModal } = useAuth();
16 | return (
17 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/apps/web/layout/DashboardLayout.tsx:
--------------------------------------------------------------------------------
1 | import { Child } from "@app/types";
2 | import { DashNav } from "./components/DashboardNav";
3 |
4 | export const DashboardLayout = ({ children }: Child) => {
5 | return (
6 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/apps/web/layout/FormBuilderLayout.tsx:
--------------------------------------------------------------------------------
1 | import { Child } from "@app/types";
2 | import { FormBuilderNav } from "./components/FormBuilderNav";
3 |
4 | export const FormBuilderLayout = ({ children }: Child) => {
5 | return (
6 |
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/apps/web/layout/HomeLayout.tsx:
--------------------------------------------------------------------------------
1 | import { Child } from "@app/types";
2 | import { MainNav } from "./components/MainNav";
3 |
4 | export const HomeLayout = ({ children }: Child) => {
5 | return (
6 | <>
7 |
8 | {children}
9 | >
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/apps/web/layout/components/DashBoardRoute.tsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from "next/router";
2 | import { IconType } from "react-icons";
3 |
4 | export const DashBoardRoute = ({ Icon, name }: Props) => {
5 | const router = useRouter();
6 |
7 | const { id, eventid } = router.query;
8 | return (
9 | router.push(`/org/${id}/${eventid}/${name.toLowerCase()}`)}
12 | >
13 |
14 | {name}
15 |
16 | );
17 | };
18 |
19 | interface Props {
20 | Icon: IconType;
21 | name: string;
22 | }
23 |
--------------------------------------------------------------------------------
/apps/web/layout/components/MainNav.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link";
2 | import { useRouter } from "next/router";
3 | import { Button } from "@app/components/ui/Button";
4 | import { useAuth } from "@app/hooks";
5 | import { AuthModal } from "../AuthModal";
6 | import { UserNav } from "./UserNav";
7 |
8 | export const MainNav = () => {
9 | const router = useRouter();
10 | const { user, toggleModal } = useAuth();
11 | return (
12 |
13 |
14 |
15 |
16 | fossfolio
17 |
18 |
19 |
20 |
21 |
router.push("/")}
24 | >
25 | Home
26 |
27 |
28 |
29 | Events
30 |
31 |
32 |
33 | {user ? (
34 |
35 | ) : (
36 |
39 | )}
40 |
41 |
42 | );
43 | };
44 |
--------------------------------------------------------------------------------
/apps/web/layout/components/constants.ts:
--------------------------------------------------------------------------------
1 | import { FiHome, FiUser, FiSettings, FiBarChart } from "react-icons/fi";
2 | import { FaWpforms } from "react-icons/fa";
3 | import { BsPeople } from "react-icons/bs";
4 |
5 | export const ROUTES = [
6 | {
7 | name: "Event",
8 | icon: FiHome,
9 | },
10 | {
11 | name: "Participants",
12 | icon: FiUser,
13 | },
14 | {
15 | name: "Form",
16 | icon: FaWpforms,
17 | },
18 | {
19 | name: "Tasks",
20 | icon: BsPeople,
21 | },
22 | {
23 | name: "Revenue",
24 | icon: FiBarChart,
25 | },
26 | ];
27 |
28 | export const FORM_BUILDER_ROUTES = [
29 | {
30 | name: "Builder",
31 | icon: FiHome,
32 | },
33 | {
34 | name: "Responses",
35 | icon: FiUser,
36 | },
37 | {
38 | name: "Analytics",
39 | icon: FaWpforms,
40 | },
41 | ];
42 |
--------------------------------------------------------------------------------
/apps/web/layout/index.ts:
--------------------------------------------------------------------------------
1 | export { HomeLayout } from "./HomeLayout";
2 | export { DashboardLayout } from "./DashboardLayout";
3 | export { FormBuilderLayout } from "./FormBuilderLayout";
4 |
--------------------------------------------------------------------------------
/apps/web/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/apps/web/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | swcMinify: true,
5 | typescript: {
6 | ignoreBuildErrors: true,
7 | },
8 | images: {
9 | domains: [
10 | "img.freepik.com",
11 | "fossfolio.s3.amazonaws.com",
12 | "loremflickr.com",
13 | "picsum.photos",
14 | "fossfolio.s3.us-east-1.amazonaws.com",
15 | ],
16 | },
17 | };
18 |
19 | module.exports = nextConfig;
20 |
--------------------------------------------------------------------------------
/apps/web/next.d.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | NextComponentType,
3 | NextPageContext,
4 | NextLayoutComponentType,
5 | NextPage,
6 | } from "next";
7 | import type { AppProps } from "next/app";
8 | import { Child } from "./types";
9 |
10 | declare module "next" {
11 | type NextLayoutComponentType = NextComponentType<
12 | NextPageContext,
13 | any,
14 | P
15 | > & {
16 | Layout?: (page: ReactNode) => ReactNode;
17 | RequireAuth: boolean;
18 | };
19 |
20 | type NextPageWithLayout = NextPage & {
21 | Layout: (arg0: Child) => JSX.Element;
22 | RequireAuth: boolean;
23 | };
24 | }
25 |
26 | declare module "next/app" {
27 | type AppLayoutProps
= AppProps & {
28 | Component: NextLayoutComponentType;
29 | };
30 | }
31 |
--------------------------------------------------------------------------------
/apps/web/pages/404.tsx:
--------------------------------------------------------------------------------
1 | import { NextPageWithLayout } from "next";
2 | import { HomeLayout } from "@app/layout";
3 | import { Error as ErrorPage } from "@app/components/Error";
4 | const Error: NextPageWithLayout = () => ;
5 |
6 | Error.Layout = HomeLayout;
7 | Error.RequireAuth = false;
8 | export default Error;
9 |
--------------------------------------------------------------------------------
/apps/web/pages/[org].tsx:
--------------------------------------------------------------------------------
1 | import { EventCard, NoData, PreLoader } from "@app/components/events";
2 | import { usePublicOrgEvents } from "@app/hooks/api/Events";
3 | import { HomeLayout } from "@app/layout";
4 | import { NextPageWithLayout } from "next";
5 |
6 | const Event: NextPageWithLayout = () => {
7 | const { data, isLoading } = usePublicOrgEvents();
8 |
9 | if (isLoading) {
10 | return ;
11 | }
12 |
13 | if (data?.data.events.length === 0) {
14 | return (
15 |
16 |
Find Events
17 |
18 |
19 |
20 |
21 | );
22 | }
23 |
24 | return (
25 |
26 |
{data?.data.name.toUpperCase()}
27 |
28 | {data?.data.events.map((el) => (
29 |
40 | ))}
41 |
42 |
43 | );
44 | };
45 |
46 | Event.Layout = HomeLayout;
47 | Event.RequireAuth = false;
48 | export default Event;
49 |
--------------------------------------------------------------------------------
/apps/web/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { HomeLayout } from "@app/layout";
2 | import { motion } from "framer-motion";
3 | import Image from "next/image";
4 | import Link from "next/link";
5 | import { AnimatedCharacters } from "@app/views/home";
6 | import { NextPageWithLayout } from "next";
7 | import { Button } from "@app/components/ui/Button";
8 |
9 | const container = {
10 | visible: {
11 | transition: {
12 | staggerChildren: 0.025,
13 | },
14 | },
15 | };
16 |
17 | const Head = ["Discover, host and manage Events, Hackathons all in one place."];
18 |
19 | const Home: NextPageWithLayout = () => {
20 | return (
21 |
22 |
23 |
29 | {Head.map((el, key) => (
30 |
31 | ))}
32 |
33 |
34 |
37 |
40 |
41 |
42 |
43 |
49 |
50 |
51 | );
52 | };
53 |
54 | Home.Layout = HomeLayout;
55 | Home.RequireAuth = false;
56 | export default Home;
57 |
--------------------------------------------------------------------------------
/apps/web/pages/org/[id]/[eventid]/form/[formid]/index.tsx:
--------------------------------------------------------------------------------
1 | import { PageLoader } from "@app/components/preloaders";
2 | import { HomeLayout } from "@app/layout";
3 |
4 | export const Index = () => {
5 | return ;
6 | };
7 | export async function getServerSideProps(ctx: any) {
8 | const accesToken = ctx.req.cookies["access_token"];
9 | const url = ctx.req.url as string;
10 | const length = url.split("/").length;
11 | const formId = url.split("/")[length - 1];
12 | const eventid = url.split("/")[length - 2];
13 | const orgId = url.split("/")[length - 3];
14 | if (!accesToken) {
15 | return {
16 | redirect: {
17 | destination: "/",
18 | permanent: false,
19 | },
20 | };
21 | }
22 |
23 | return {
24 | redirect: {
25 | destination: `/org/${orgId}/${eventid}/form/${formId}/builder`,
26 | permanent: false,
27 | },
28 | };
29 | }
30 |
31 | Index.Layout = HomeLayout;
32 | Index.RequireAuth = true;
33 |
34 | export default Index;
35 |
--------------------------------------------------------------------------------
/apps/web/pages/org/[id]/[eventid]/index.tsx:
--------------------------------------------------------------------------------
1 | import { PageLoader } from "@app/components/preloaders";
2 | import { HomeLayout } from "@app/layout";
3 |
4 | export const Index = () => {
5 | return ;
6 | };
7 | export async function getServerSideProps(ctx: any) {
8 | const accesToken = ctx.req.cookies["access_token"];
9 | const url = ctx.req.url as string;
10 | const length = url.split("/").length;
11 | const eventid = url.split("/")[length - 1];
12 | const orgId = url.split("/")[length - 2];
13 | if (!accesToken) {
14 | return {
15 | redirect: {
16 | destination: "/",
17 | permanent: false,
18 | },
19 | };
20 | }
21 |
22 | return {
23 | redirect: {
24 | destination: `/org/${orgId}/${eventid}/event`,
25 | permanent: false,
26 | },
27 | };
28 | }
29 |
30 | Index.Layout = HomeLayout;
31 | Index.RequireAuth = true;
32 |
33 | export default Index;
34 |
--------------------------------------------------------------------------------
/apps/web/pages/org/[id]/[eventid]/participants.tsx:
--------------------------------------------------------------------------------
1 | import { NextPageWithLayout } from "next";
2 | import { DashboardLayout } from "@app/layout";
3 | import { Participants } from "@app/views/dashboard";
4 | import { useEventParticipants } from "@app/hooks/api/org";
5 | import { useEvent } from "@app/hooks/api/Events";
6 | import { Loader } from "@app/components/preloaders";
7 | import { TicketLottie } from "@app/views/dashboard";
8 |
9 | const Dashboard: NextPageWithLayout = () => {
10 | const { isLoading, data, refetch, error } = useEventParticipants();
11 | const { data: eventData } = useEvent("event");
12 |
13 | if (error) {
14 | return ;
15 | }
16 | if (isLoading) {
17 | return ;
18 | }
19 |
20 | if (data) {
21 | return (
22 |
23 |
24 | All Registered Participants
25 |
26 |
32 |
33 | );
34 | }
35 | };
36 |
37 | Dashboard.Layout = DashboardLayout;
38 | Dashboard.RequireAuth = true;
39 | export default Dashboard;
40 |
--------------------------------------------------------------------------------
/apps/web/pages/org/[id]/[eventid]/tasks.tsx:
--------------------------------------------------------------------------------
1 | import { useKanban } from "@app/hooks/api/kanban";
2 | import { DashboardLayout } from "@app/layout";
3 | import { Separator } from "@app/ui/components/separator";
4 | import { Kanban } from "@app/views/tasks";
5 | import { Loader } from "@app/components/preloaders";
6 | import { HTML5Backend } from "react-dnd-html5-backend";
7 | import { DndProvider } from "react-dnd";
8 | import { Button } from "@app/components/ui/Button";
9 |
10 | const Tasks = () => {
11 | const { data, isLoading, isError } = useKanban();
12 |
13 | if (isLoading) {
14 | return ;
15 | }
16 |
17 | if (isError) {
18 | return Error
;
19 | }
20 | return (
21 |
22 |
23 |
Board
24 |
25 |
26 |
27 |
28 |
29 | {data?.data.map((board) => (
30 |
31 |
32 |
33 |
34 | ))}
35 |
36 |
37 |
38 | );
39 | };
40 |
41 | Tasks.Layout = DashboardLayout;
42 | Tasks.RequireAuth = true;
43 | export default Tasks;
44 |
--------------------------------------------------------------------------------
/apps/web/pages/verify.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { useRouter } from "next/router";
3 | import { HomeLayout } from "@app/layout";
4 | import { apiHandler } from "@app/config";
5 | import { QueryClient } from "@tanstack/react-query";
6 |
7 | type Prop = {
8 | ok: boolean;
9 | orgId: string;
10 | };
11 |
12 | const Verify = ({ orgId }: Prop) => {
13 | const router = useRouter();
14 |
15 | const queryClient = new QueryClient();
16 | useEffect(() => {
17 | const verify = async () => {
18 | try {
19 | await apiHandler.get(`/org/invite/verify?id=${orgId}`);
20 | queryClient.invalidateQueries({
21 | queryKey: ["orgs"],
22 | });
23 | router.push(`/org`);
24 | } catch {
25 | router.push("/events?invite_failed=true");
26 | }
27 | };
28 | verify();
29 | // eslint-disable-next-line react-hooks/exhaustive-deps
30 | }, []);
31 |
32 | return (
33 |
34 |
35 | Verifying your email
36 |
37 |
38 | );
39 | };
40 |
41 | // used to verify the email for org
42 | export async function getServerSideProps(ctx: any) {
43 | return {
44 | props: {
45 | ok: true,
46 | orgId: ctx.query.id,
47 | },
48 | };
49 | }
50 |
51 | Verify.Layout = HomeLayout;
52 | Verify.RequireAuth = true;
53 |
54 | export default Verify;
55 |
--------------------------------------------------------------------------------
/apps/web/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/apps/web/public/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/apps/web/public/banner.png
--------------------------------------------------------------------------------
/apps/web/public/event.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/apps/web/public/event.jpg
--------------------------------------------------------------------------------
/apps/web/public/foss.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/apps/web/public/foss.png
--------------------------------------------------------------------------------
/apps/web/public/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/apps/web/public/main.png
--------------------------------------------------------------------------------
/apps/web/public/placeholder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/apps/web/public/placeholder.png
--------------------------------------------------------------------------------
/apps/web/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES6",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "@app/*": ["./*"]
20 | }
21 | },
22 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
23 | "exclude": ["node_modules"]
24 | }
25 |
--------------------------------------------------------------------------------
/apps/web/ui/components/avatar.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import * as React from "react";
4 | import * as AvatarPrimitive from "@radix-ui/react-avatar";
5 |
6 | import { cn } from "../lib/utils";
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ));
21 | Avatar.displayName = AvatarPrimitive.Root.displayName;
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ));
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName;
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ));
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
49 |
50 | export { Avatar, AvatarImage, AvatarFallback };
51 |
--------------------------------------------------------------------------------
/apps/web/ui/components/checkbox.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
3 | import { FaCheck } from "react-icons/fa";
4 |
5 | import { cn } from "ui/lib/utils";
6 |
7 | const Checkbox = React.forwardRef<
8 | React.ElementRef,
9 | React.ComponentPropsWithoutRef
10 | >(({ className, ...props }, ref) => (
11 |
19 |
22 |
23 |
24 |
25 | ));
26 | Checkbox.displayName = CheckboxPrimitive.Root.displayName;
27 |
28 | export { Checkbox };
29 |
--------------------------------------------------------------------------------
/apps/web/ui/components/input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | import { cn } from "../lib/utils";
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes {}
7 |
8 | const Input = React.forwardRef(
9 | ({ className, type, ...props }, ref) => {
10 | return (
11 |
20 | );
21 | }
22 | );
23 | Input.displayName = "Input";
24 |
25 | export { Input };
26 |
--------------------------------------------------------------------------------
/apps/web/ui/components/label.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as LabelPrimitive from "@radix-ui/react-label";
3 | import { cva, type VariantProps } from "class-variance-authority";
4 |
5 | import { cn } from "../lib/utils";
6 |
7 | const labelVariants = cva(
8 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 "
9 | );
10 |
11 | const Label = React.forwardRef<
12 | React.ElementRef,
13 | React.ComponentPropsWithoutRef &
14 | VariantProps
15 | >(({ className, ...props }, ref) => (
16 |
21 | ));
22 | Label.displayName = LabelPrimitive.Root.displayName;
23 |
24 | export { Label };
25 |
--------------------------------------------------------------------------------
/apps/web/ui/components/popover.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as PopoverPrimitive from "@radix-ui/react-popover";
3 |
4 | import { cn } from "../lib/utils";
5 |
6 | const Popover = PopoverPrimitive.Root;
7 |
8 | const PopoverTrigger = PopoverPrimitive.Trigger;
9 |
10 | const PopoverContent = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
14 |
15 |
25 |
26 | ));
27 | PopoverContent.displayName = PopoverPrimitive.Content.displayName;
28 |
29 | export { Popover, PopoverTrigger, PopoverContent };
30 |
--------------------------------------------------------------------------------
/apps/web/ui/components/separator.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as SeparatorPrimitive from "@radix-ui/react-separator";
3 |
4 | import { cn } from "../lib/utils";
5 |
6 | const Separator = React.forwardRef<
7 | React.ElementRef,
8 | React.ComponentPropsWithoutRef
9 | >(
10 | (
11 | { className, orientation = "horizontal", decorative = true, ...props },
12 | ref
13 | ) => (
14 |
25 | )
26 | );
27 | Separator.displayName = SeparatorPrimitive.Root.displayName;
28 |
29 | export { Separator };
30 |
--------------------------------------------------------------------------------
/apps/web/ui/components/skeleton.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "../lib/utils";
2 |
3 | function Skeleton({
4 | className,
5 | ...props
6 | }: React.HTMLAttributes) {
7 | return (
8 |
12 | );
13 | }
14 |
15 | export { Skeleton };
16 |
--------------------------------------------------------------------------------
/apps/web/ui/components/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 |
3 | import { cn } from "ui/lib/utils";
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | );
20 | }
21 | );
22 | Textarea.displayName = "Textarea";
23 |
24 | export { Textarea };
25 |
--------------------------------------------------------------------------------
/apps/web/ui/components/tooltip.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import * as TooltipPrimitive from "@radix-ui/react-tooltip";
3 |
4 | import { cn } from "../lib/utils";
5 |
6 | const TooltipProvider = TooltipPrimitive.Provider;
7 |
8 | const Tooltip = TooltipPrimitive.Root;
9 |
10 | const TooltipTrigger = TooltipPrimitive.Trigger;
11 |
12 | const TooltipContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, sideOffset = 4, ...props }, ref) => (
16 |
25 | ));
26 | TooltipContent.displayName = TooltipPrimitive.Content.displayName;
27 |
28 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
29 |
--------------------------------------------------------------------------------
/apps/web/ui/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { type ClassValue, clsx } from "clsx";
2 | import { twMerge } from "tailwind-merge";
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs));
6 | }
7 |
--------------------------------------------------------------------------------
/apps/web/utils/convert2base64.ts:
--------------------------------------------------------------------------------
1 | export const convert2base64 = (
2 | file: File,
3 | selectCover: (name: string | undefined) => void
4 | ) => {
5 | const reader = new FileReader();
6 |
7 | reader.onloadend = () => [selectCover(reader.result?.toString())];
8 |
9 | reader.readAsDataURL(file);
10 | };
11 |
--------------------------------------------------------------------------------
/apps/web/utils/debounce.ts:
--------------------------------------------------------------------------------
1 | export const debounce = (fn: Function, ms = 2000) => {
2 | let timeoutId: ReturnType;
3 | // eslint-disable-next-line func-names
4 | return function (this: any, ...args: any[]) {
5 | clearTimeout(timeoutId);
6 | timeoutId = setTimeout(() => fn.apply(this, args), ms);
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/apps/web/utils/index.ts:
--------------------------------------------------------------------------------
1 | export { debounce } from "./debounce";
2 | export { isProd } from "./isProd";
3 | export { pluralize } from "./pluralize";
4 | export { convert2base64 } from "./convert2base64";
5 |
--------------------------------------------------------------------------------
/apps/web/utils/isProd.ts:
--------------------------------------------------------------------------------
1 | export const isProd = process.env.NODE_ENV === "production";
2 |
--------------------------------------------------------------------------------
/apps/web/utils/pluralize.ts:
--------------------------------------------------------------------------------
1 | export const pluralize = (
2 | word: string,
3 | count: number,
4 | shouldCombine = false
5 | ) => {
6 | if (count <= 1) {
7 | if (shouldCombine) {
8 | return `${count} ${word}`;
9 | } else {
10 | return word;
11 | }
12 | }
13 | if (count > 1) {
14 | if (shouldCombine) {
15 | return `${count} ${word}s`;
16 | } else {
17 | return `${word}s`;
18 | }
19 | }
20 |
21 | return `${count} ${word}`;
22 | };
23 |
--------------------------------------------------------------------------------
/apps/web/views/dashboard/components/ComingSoon.tsx:
--------------------------------------------------------------------------------
1 | import { useLottie } from "lottie-react";
2 | import ComingSoo from "@app/public/lottie/coming.json";
3 |
4 | export const ComingSoon = () => {
5 | const defaultOptions = {
6 | loop: true,
7 | autoplay: true,
8 | animationData: ComingSoo,
9 | rendererSettings: {
10 | preserveAspectRatio: "xMidYMid slice",
11 | },
12 | };
13 |
14 | const { View } = useLottie(defaultOptions);
15 |
16 | return (
17 |
18 | {typeof window !== undefined && <>{View}>}
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/apps/web/views/dashboard/components/lottie/TicketLottie.tsx:
--------------------------------------------------------------------------------
1 | import { useLottie } from "lottie-react";
2 | import Ticket from "@app/public/lottie/ticketsLottie.json";
3 | import { Button } from "@app/components/ui/Button";
4 |
5 | export const TicketLottie = () => {
6 | const defaultOptions = {
7 | loop: false,
8 | autoplay: true,
9 | animationData: Ticket,
10 | rendererSettings: {
11 | preserveAspectRatio: "xMidYMid slice",
12 | },
13 | };
14 |
15 | const { View } = useLottie(defaultOptions);
16 | return (
17 | <>
18 |
19 | {typeof window !== undefined && <>{View}>}
20 |
21 |
22 | Please Configure Tickets To Access Participants Page
23 |
24 |
31 |
32 |
33 | >
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/apps/web/views/dashboard/components/settings/DeleteEvent.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@app/components/ui/Button";
2 | import { useRoles } from "@app/hooks";
3 | import { Card, CardContent } from "@app/ui/components/card";
4 |
5 | interface DeleteEvent {
6 | deleteEvent: () => Promise;
7 | isLoading: boolean;
8 | }
9 |
10 | export const DeleteEvent = ({ deleteEvent, isLoading }: DeleteEvent) => {
11 | const { canDeleteEvent } = useRoles();
12 |
13 | if (canDeleteEvent) {
14 | return (
15 |
16 |
17 |
18 |
Deleting the Events will delete its all data
19 |
26 |
27 |
28 |
29 | );
30 | }
31 |
32 | return null;
33 | };
34 |
--------------------------------------------------------------------------------
/apps/web/views/dashboard/index.ts:
--------------------------------------------------------------------------------
1 | export { Participants } from "./components/participants/Participants";
2 | export { Teams } from "./components/teams/Teams";
3 | export { NewEventDialog } from "./components/settings/NewEventModal";
4 | export { PublishModal, EventSchema } from "./components/settings/PublishModal";
5 | export type { IProfile } from "./components/settings/PublishModal";
6 | export { ComingSoon } from "./components/ComingSoon";
7 | export { DeleteEvent } from "./components/settings/DeleteEvent";
8 | export { TicketLottie } from "./components/lottie/TicketLottie";
9 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/builder/AvailableFields.tsx:
--------------------------------------------------------------------------------
1 | import { InputOption } from "@app/views/form";
2 | import { Fields } from "./Field";
3 |
4 | export const AvailableFields = () => {
5 | return (
6 |
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/builder/Field.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "@app/ui/lib/utils";
2 | import { useRef } from "react";
3 | import { useDrag } from "react-dnd";
4 | import { DROP_FIELD } from "../../constants";
5 |
6 | interface Prop {
7 | label: string;
8 | value: string;
9 | }
10 |
11 | export const Fields = ({ label, value }: Prop) => {
12 | const ref = useRef(null);
13 | const [{ isDragging }, drag] = useDrag(() => ({
14 | type: DROP_FIELD,
15 | item: { id: value },
16 | collect: (monitor) => ({
17 | isDragging: monitor.isDragging(),
18 | }),
19 | }));
20 |
21 | drag(ref);
22 |
23 | return (
24 |
31 | {label}
32 |
33 | );
34 | };
35 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/common.ts:
--------------------------------------------------------------------------------
1 | import * as yup from "yup";
2 |
3 | export const NewFormValidationSchema = yup.object().shape({
4 | title: yup.string().required(),
5 | description: yup.string().required().max(25),
6 | });
7 |
8 | export type NewFormSchema = yup.InferType;
9 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/dashboard/FormsLoader.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardContent } from "@app/ui/components/card";
2 | import React from "react";
3 | import { Button } from "@app/components/ui/Button";
4 | import { Skeleton } from "@app/ui/components/skeleton";
5 | import { LuClipboard } from "react-icons/lu";
6 |
7 | type Props = {
8 | count: number;
9 | };
10 |
11 | export const FormsLoader = ({ count }: Props) => {
12 | return (
13 | <>
14 | {new Array(count).fill(0).map((el, index) => (
15 |
16 |
17 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 | ))}
37 | >
38 | );
39 | };
40 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/public/PublicFormModal.tsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogContent } from "@app/ui/components/dialog";
2 |
3 | import { Iform } from "@app/types";
4 | import { SchemaPreview } from "./SchemaPreview";
5 | import { useEvent } from "@app/hooks/api/Events";
6 |
7 | type IModal = {
8 | isOpen: boolean;
9 | onClose: () => void;
10 | schema: Iform[];
11 | };
12 |
13 | export const PublicFormModal = ({ isOpen, onClose, schema }: IModal) => {
14 | const { data } = useEvent("public");
15 | return (
16 |
26 | );
27 | };
28 |
--------------------------------------------------------------------------------
/apps/web/views/form/components/types.ts:
--------------------------------------------------------------------------------
1 | type Iinput =
2 | | "SingleLineText"
3 | | "LongText"
4 | | "SingleSelect"
5 | | "MultiSelect"
6 | | "Checkbox"
7 | | "Number"
8 | | "Email"
9 | | "URL"
10 | | "PhoneNumber"
11 | | "Attachment";
12 |
13 | // v0 does not support attachment
14 | export type IFormInput = Exclude;
15 |
16 | type IinputOption = {
17 | label: string;
18 | value: IFormInput;
19 | };
20 |
21 | export const InputOption: IinputOption[] = [
22 | {
23 | label: "Single line text",
24 | value: "SingleLineText",
25 | },
26 | {
27 | label: "Long text",
28 | value: "LongText",
29 | },
30 | {
31 | label: "SingleSelect",
32 | value: "SingleSelect",
33 | },
34 | {
35 | label: "Multi select",
36 | value: "MultiSelect",
37 | },
38 | {
39 | label: "Checkbox",
40 | value: "Checkbox",
41 | },
42 | {
43 | label: "Email",
44 | value: "Email",
45 | },
46 | {
47 | label: "Number",
48 | value: "Number",
49 | },
50 | {
51 | label: "URL",
52 | value: "URL",
53 | },
54 | {
55 | label: "PhoneNumber",
56 | value: "PhoneNumber",
57 | },
58 | ];
59 |
--------------------------------------------------------------------------------
/apps/web/views/form/constants.ts:
--------------------------------------------------------------------------------
1 | export const DROP_FIELD = "FIELD";
2 |
3 | export const DROP_IMAGE = "COVER_IMAGE";
4 |
--------------------------------------------------------------------------------
/apps/web/views/form/index.ts:
--------------------------------------------------------------------------------
1 | export * from "./components/types";
2 | export { SchemaPreview } from "./components/public/SchemaPreview";
3 | export { PublicFormModal } from "./components/public/PublicFormModal";
4 | export { FormsLoader } from "./components/dashboard/FormsLoader";
5 | export { AvailableFields } from "./components/builder/AvailableFields";
6 | export { BuilderPreview } from "./components/builder/BuilderPreview";
7 | export { BuilderConfig } from "./components/builder/BuilderConfig";
8 | export { NewFormDialog } from "./components/dashboard/NewFormModal";
9 |
--------------------------------------------------------------------------------
/apps/web/views/home/index.ts:
--------------------------------------------------------------------------------
1 | export { AnimatedCharacters } from "./components/Animate";
2 |
--------------------------------------------------------------------------------
/apps/web/views/org/components/dashboard/OrgCard.tsx:
--------------------------------------------------------------------------------
1 | import { useAuth } from "@app/hooks";
2 | import { Roles } from "@app/types";
3 | import { pluralize } from "@app/utils";
4 | import { useRouter } from "next/router";
5 | import { BsChevronRight } from "react-icons/bs";
6 | import { IoIosList, IoMdPeople } from "react-icons/io";
7 |
8 | type Prop = {
9 | name: string;
10 | id: string;
11 | role: Roles;
12 | events: number;
13 | members: number;
14 | };
15 |
16 | export const OrgCard = ({ name, id, role, members, events }: Prop) => {
17 | const router = useRouter();
18 | const { setRole } = useAuth();
19 |
20 | const goToOrg = () => {
21 | setRole(role);
22 | router.push(`/org/${id}`);
23 | };
24 |
25 | return (
26 |
30 |
31 |
{name}
32 |
33 |
34 |
35 |
36 |
37 | {pluralize("Event", events, true)}
38 |
39 |
40 |
41 | {pluralize("Member", members, true)}
42 |
43 |
44 |
45 | );
46 | };
47 |
--------------------------------------------------------------------------------
/apps/web/views/org/components/dashboard/SkeltonCard.tsx:
--------------------------------------------------------------------------------
1 | import { Skeleton } from "@app/ui/components/skeleton";
2 |
3 | export function SkeletonCard() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/apps/web/views/org/components/settings/DeleteOrg.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardContent, CardHeader } from "@app/ui/components/card";
2 | import { Button } from "@app/ui/components/button";
3 | import { useToggle } from "@app/hooks";
4 | import { DeleteModal } from "./DeleteModal";
5 |
6 | export const DeleteOrg = () => {
7 | const [isOpen, triggerModal] = useToggle(false);
8 | return (
9 |
10 |
11 |
12 |
13 |
Delete this Organization
14 |
15 | Deleting the organization will delete its all members and all the
16 | events associated with the organization
17 |
18 |
19 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
--------------------------------------------------------------------------------
/apps/web/views/org/components/settings/LeaveOrg.tsx:
--------------------------------------------------------------------------------
1 | import { Card, CardContent } from "@app/ui/components/card";
2 | import { Button } from "@app/ui/components/button";
3 | import { useToggle } from "@app/hooks";
4 | import { LeaveModal } from "./LeaveModal";
5 |
6 | export const LeaveOrg = () => {
7 | const [isOpen, triggerModal] = useToggle(false);
8 | return (
9 |
10 |
11 |
12 |
13 |
Leave this Organization
14 |
15 | You are about to leave this organization. This action is
16 | irreversible. Are you sure you want to leave?
17 |
18 |
19 |
26 |
27 |
28 |
29 |
30 | );
31 | };
32 |
--------------------------------------------------------------------------------
/apps/web/views/org/components/teams/RemoveMemberModal.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@app/components/ui/Button";
2 | import {
3 | Dialog,
4 | DialogContent,
5 | DialogDescription,
6 | DialogHeader,
7 | } from "@app/ui/components/dialog";
8 | import { useRemoveMember } from "@app/hooks/api/org";
9 |
10 | type IModal = {
11 | isOpen: boolean;
12 | onClose: () => void;
13 | memberName: string;
14 | memberId: string;
15 | };
16 |
17 | export const RemoveMemberModal = ({
18 | isOpen,
19 | onClose,
20 | memberName,
21 | memberId,
22 | }: IModal) => {
23 | const { mutate, isLoading } = useRemoveMember();
24 |
25 | return (
26 |
52 | );
53 | };
54 |
--------------------------------------------------------------------------------
/apps/web/views/org/index.ts:
--------------------------------------------------------------------------------
1 | export { OrgCard } from "./components/dashboard/OrgCard";
2 | export { SkeletonCard } from "./components/dashboard/SkeltonCard";
3 | export { NewOrgDialog } from "./components/dashboard/NewOrgDialog";
4 | export { DeleteOrg } from "./components/settings/DeleteOrg";
5 | export { Events } from "./components/events/Events";
6 | export { LeaveOrg } from "./components/settings/LeaveOrg";
7 | export { InviteModal } from "./components/teams/InviteModal";
8 | export { OrgSettings } from "./components/settings/OrgSettings";
9 | export { Members } from "./components/teams/Members";
10 |
--------------------------------------------------------------------------------
/apps/web/views/profile/index.ts:
--------------------------------------------------------------------------------
1 | export { ProfileModal } from "./components/ProfileModal";
2 |
--------------------------------------------------------------------------------
/apps/web/views/tasks/components/KanbanTask.tsx:
--------------------------------------------------------------------------------
1 | import { clsx } from "clsx";
2 | import { Toggle } from "@app/hooks/useToggle";
3 | import { Task } from "@app/types";
4 | import { Card } from "@app/ui/components/card";
5 | import { useDrag } from "react-dnd";
6 | import { useRef } from "react";
7 |
8 | interface Prop {
9 | setTaskPreview: React.Dispatch;
10 | setTaskPreviewPane: Toggle;
11 | data: Task;
12 | }
13 |
14 | export const KanbanTask = ({
15 | setTaskPreview,
16 | setTaskPreviewPane,
17 | data,
18 | }: Prop) => {
19 | const ref = useRef(null);
20 |
21 | const [{ isDragging }, drag] = useDrag(
22 | () => ({
23 | type: "TASK",
24 | item: {
25 | id: data.id,
26 | },
27 | collect: (monitor) => ({
28 | isDragging: monitor.isDragging(),
29 | }),
30 | }),
31 | [data.id]
32 | );
33 |
34 | // for fixing ts-issue
35 | drag(ref);
36 |
37 | const handlePreviewPane = () => {
38 | setTaskPreview(data);
39 | setTaskPreviewPane.on();
40 | };
41 |
42 | return (
43 |
51 | {data.title}
52 |
53 | );
54 | };
55 |
--------------------------------------------------------------------------------
/apps/web/views/tasks/components/TaskPreviewPane.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@app/components/ui/Button";
2 | import { Comments } from "@app/types";
3 | import { Editor } from "novel";
4 | import Drawer from "react-modern-drawer";
5 | import "react-modern-drawer/dist/index.css";
6 |
7 | type Props = {
8 | open: boolean;
9 | onClose: () => void;
10 | title: string;
11 | description: Comments[];
12 | storageKey: string;
13 | };
14 |
15 | export const TaskPreviewPane = ({
16 | open,
17 | onClose,
18 | title,
19 | description,
20 | storageKey,
21 | }: Props) => {
22 | const handleClose = () => {
23 | localStorage.clear();
24 | onClose();
25 | };
26 |
27 | return (
28 |
35 |
36 |
{title}
37 |
38 |
39 | {description.map((desc) => (
40 |
47 | ))}
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | );
56 | };
57 |
--------------------------------------------------------------------------------
/apps/web/views/tasks/index.ts:
--------------------------------------------------------------------------------
1 | export { Kanban } from "./components/Kanban";
2 | export { KanbanTask } from "./components/KanbanTask";
3 |
--------------------------------------------------------------------------------
/apps/web/views/tickets/index.ts:
--------------------------------------------------------------------------------
1 | export { TicketCard } from "./components/TicketCard";
2 | export { TicketModal } from "./components/TicketModal";
3 |
--------------------------------------------------------------------------------
/apps/web/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vitest/config";
2 | import react from "@vitejs/plugin-react";
3 | import path from "path";
4 |
5 | export default defineConfig({
6 | plugins: [react()],
7 | test: {
8 | environment: "jsdom",
9 | dir: "./__tests__",
10 | exclude: ["./e2e"],
11 | alias: {
12 | "@app": path.resolve(__dirname),
13 | },
14 | },
15 | });
16 |
--------------------------------------------------------------------------------
/docker-compose.yaml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 | services:
3 | db:
4 | image: pgvector/pgvector:pg16
5 | volumes:
6 | - pg-data:/data/db
7 | ports:
8 | - 5432:5432
9 | env_file:
10 | - .env
11 | environment:
12 | - POSTGRES_USER=${DB_USER}
13 | - POSTGRES_PASSWORD=${DB_PASS}
14 | - POSTGRES_DB=${DB_NAME}
15 | healthcheck:
16 | test: ['CMD-SHELL', 'pg_isready -U ${DB_USER}']
17 | interval: 5s
18 | timeout: 5s
19 | retries: 5
20 | networks:
21 | - app_network
22 | volumes:
23 | pg-data:
24 | driver: local
25 | networks:
26 | app_network:
27 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fossfolio",
3 | "version": "1.0.0",
4 | "private": true,
5 | "workspaces": [
6 | "apps/*",
7 | "packages/*"
8 | ],
9 | "scripts": {
10 | "build": "turbo run build",
11 | "dev": "turbo run dev --parallel",
12 | "lint": "turbo run lint",
13 | "turbo": "turbo",
14 | "api-dev": "pnpm --filter api dev",
15 | "web-dev": "pnpm --filter web dev"
16 | },
17 | "devDependencies": {
18 | "turbo": "latest"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/docs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/.gitkeep
--------------------------------------------------------------------------------
/packages/docs/all-events.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/all-events.png
--------------------------------------------------------------------------------
/packages/docs/editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/editor.png
--------------------------------------------------------------------------------
/packages/docs/event.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/event.png
--------------------------------------------------------------------------------
/packages/docs/members.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/members.png
--------------------------------------------------------------------------------
/packages/docs/orgs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/orgs.png
--------------------------------------------------------------------------------
/packages/docs/particpents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/particpents.png
--------------------------------------------------------------------------------
/packages/docs/profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/profile.png
--------------------------------------------------------------------------------
/packages/docs/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/foss-labs/fossfolio/e460e337c1a2ca3e5854bde346aafa7e3a235252/packages/docs/settings.png
--------------------------------------------------------------------------------
/packages/infra/.terraform.lock.hcl:
--------------------------------------------------------------------------------
1 | # This file is maintained automatically by "terraform init".
2 | # Manual edits may be lost in future updates.
3 |
4 | provider "registry.terraform.io/hashicorp/aws" {
5 | version = "3.76.1"
6 | constraints = "~> 3.27"
7 | hashes = [
8 | "h1:z1+WjdwuRX8Aa9a7YKXErhZ5AuvoXiDq7FHts30sZak=",
9 | "zh:1cf933104a641ffdb64d71a76806f4df35d19101b47e0eb02c9c36bd64bfdd2d",
10 | "zh:273afaf908775ade6c9d32462938e7739ee8b00a0de2ef3cdddc5bc115bb1d4f",
11 | "zh:2bc24ae989e38f575de034083082c69b41c54b8df69d35728853257c400ce0f4",
12 | "zh:53ba88dbdaf9f818d35001c3d519a787f457283d9341f562dc3d0af51fd9606e",
13 | "zh:5cdac7afea68bbd89d3bdb345d99470226482eff41f375f220fe338d2e5808da",
14 | "zh:63127808890ac4be6cff6554985510b15ac715df698d550a3e722722dc56523c",
15 | "zh:97a1237791f15373743189b078a0e0f2fa4dd7d7474077423376cd186312dc55",
16 | "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
17 | "zh:a4f625e97e5f25073c08080e4a619f959bc0149fc853a6b1b49ab41d58b59665",
18 | "zh:b56cca54019237941f7614e8d2712586a6ab3092e8e9492c70f06563259171e9",
19 | "zh:d4bc33bfd6ac78fb61e6d48a61c179907dfdbdf149b89fb97272c663989a7fcd",
20 | "zh:e0089d73fa56d128c574601305634a774eebacf4a84babba71da10040cecf99a",
21 | "zh:e957531f1d92a6474c9b02bd9200da91b99ba07a0ab761c8e3176400dd41721c",
22 | "zh:eceb85818d57d8270db4df7564cf4ed51b5c650a361aaa017c42227158e1946b",
23 | "zh:f565e5caa1b349ec404c6d03d01c68b02233f5485ed038d0aab810dd4023a880",
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/infra/main.tf:
--------------------------------------------------------------------------------
1 | resource "aws_s3_bucket" "fossfolio" {
2 | bucket = "fossfolio"
3 | acl = "public"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/infra/provide.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 0.12"
3 | required_providers {
4 | aws = {
5 | source = "hashicorp/aws"
6 | version = "~> 3.27"
7 | }
8 | }
9 | }
10 |
11 |
12 | provider "aws" {
13 | region = "us-east-1"
14 | }
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "packages/*"
3 | - "apps/*"
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "compilerOptions": {
4 | "experimentalDecorators": true,
5 | "target": "ES6",
6 | "lib": ["dom", "dom.iterable", "esnext"],
7 | "allowJs": false,
8 | "skipLibCheck": true,
9 | "strict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "noEmit": false,
12 | "esModuleInterop": true,
13 | "module": "esnext",
14 | "moduleResolution": "node",
15 | "resolveJsonModule": true,
16 | "isolatedModules": true,
17 | "noUnusedParameters": true,
18 | "removeComments": true
19 | },
20 | "exclude": ["node_modules", "apps/**/lib", "apps/**/build"]
21 | }
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turborepo.org/schema.json",
3 | "pipeline": {
4 | "build": {
5 | "dependsOn": [],
6 | "outputs": ["build/**", "lib/**", ".next/**", "!.next/cache/**"]
7 | },
8 | "web#build": {
9 | "dependsOn": ["^build"],
10 | "outputs": ["dist/**"]
11 | },
12 | "start": {
13 | "dependsOn": [],
14 | "outputs": []
15 | },
16 | "lint": {
17 | "outputs": []
18 | },
19 | "format": {
20 | "outputs": []
21 | },
22 | "dev": {
23 | "outputs": []
24 | }
25 | },
26 | "globalEnv": [
27 | "NEXT_PUBLIC_API_URL",
28 | "NEXT_PUBLIC_WEBSITE_DOMAIN",
29 | "NEXT_PUBLIC_POSTHOG_KEY",
30 | "NEXT_PUBLIC_POSTHOG_HOST",
31 | "MISTRAL_API_KEY",
32 | "NODE_ENV",
33 | "PORT",
34 | "NEXT_PUBLIC_POSTHOG_KEY",
35 | "NEXT_PUBLIC_POSTHOG_HOST",
36 | "CI",
37 | "OPEN_AI_TOKEN",
38 | "AWS_ACCESS_KEY",
39 | "AWS_SECRET_KEY"
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------