Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement projects tab section #56

Merged
merged 20 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 18 additions & 43 deletions apps/api/auth/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ interface ResponseWrapper<T, E> {
const response = <T, E>(data: T, error?: E): ResponseWrapper<T, E> => {
return {
data,
error
error,
};
};

type Bindings = {
DB: D1Database;
BUCKET: R2Bucket;
}
};

const app = new Hono<{ Bindings: Bindings }>();

Expand Down Expand Up @@ -46,7 +46,7 @@ app.get('/users', async (c) => {
op.name 'provider',
oa.created_at 'createdAt',
oa.updated_at 'updatedAt'
FROM oauth_account as oa
FROM oauth_account as oa
JOIN user as u ON (oa.user_id = u.id)
JOIN oauth_provider as op ON (oa.oauth_provider_id = op.id)
WHERE u.id = ?1 AND oa.deleted_at IS NULL
Expand Down Expand Up @@ -75,17 +75,13 @@ interface User {
deleted_at: number;
}

type CreateUserParams = Pick<User,
| 'username'
| 'firstName'
| 'lastName'
>;
type CreateUserParams = Pick<User, 'username' | 'firstName' | 'lastName'>;

interface CreateOAuthParams {
oaid: string;
provider: string;
email: string;
};
}

type CreateUserRequest = CreateUserParams & CreateOAuthParams;

Expand All @@ -106,10 +102,7 @@ app.post('/users', async (c) => {

const id = typeid('user').toString();

const results = await c.env.DB.batch([
createUserStatement.bind(id, body.username, body.firstName, body.lastName, Date.now()),
createOAuthAccountStatement.bind(body.oaid, id, body.provider, body.email, Date.now()),
]);
const results = await c.env.DB.batch([createUserStatement.bind(id, body.username, body.firstName, body.lastName, Date.now()), createOAuthAccountStatement.bind(body.oaid, id, body.provider, body.email, Date.now())]);

return c.json(response(results));
});
Expand All @@ -122,9 +115,7 @@ interface OAuthProvider {
deleted_at: number;
}

type CreateOAuthProviderParams = Pick<OAuthProvider,
| 'name'
>;
type CreateOAuthProviderParams = Pick<OAuthProvider, 'name'>;

app.get('/providers', async (c) => {
const findOAuthProviderStatement = c.env.DB.prepare(`
Expand Down Expand Up @@ -163,24 +154,17 @@ interface Template {
createdAt: number;
updatedAt: number;
deletedAt: number;
};
}

type CreateTemplateParams = Pick<Template,
| 'name'
| 'userId'
>;
type CreateTemplateParams = Pick<Template, 'name' | 'userId'>;

type FindTemplateParams = Pick<Template,
| 'userId'
>;
type FindTemplateParams = Pick<Template, 'userId'>;

interface TemplateDataParams {
data: JSON;
};
}

type UpdateTemplateParams = Pick<Template,
| 'name'
>;
type UpdateTemplateParams = Pick<Template, 'name'>;

type CreateTemplateRequest = CreateTemplateParams & TemplateDataParams;
type UpdateTemplateRequest = UpdateTemplateParams & TemplateDataParams;
Expand All @@ -193,7 +177,7 @@ app.post('/templates', async (c) => {
const key = ['templates', body.userId, id].join('/');

const createTemplateStatement = c.env.DB.prepare(`
INSERT INTO template (id, user_id, name, created_at)
INSERT INTO template (id, user_id, name, created_at)
VALUES (?1, ?2, ?3, ?4)
`);

Expand Down Expand Up @@ -247,7 +231,7 @@ app.get('/templates/:userId/:id', async (c) => {

app.put('/templates/:userId/:id', async (c) => {
const { userId, id } = c.req.param();
const { data, name } = await c.req.json() as UpdateTemplateRequest;
const { data, name } = (await c.req.json()) as UpdateTemplateRequest;

const key = ['templates', userId, id].join('/');

Expand Down Expand Up @@ -276,22 +260,13 @@ interface Project {
createdAt: number;
updatedAt: number;
deletedAt: number;
};
}

type CreateProjectRequest = Pick<Project,
| 'userId'
| 'templateId'
| 'name'
>;
type CreateProjectRequest = Pick<Project, 'userId' | 'templateId' | 'name'>;

type FindProjectRequest = Pick<Project,
| 'userId'
>;
type FindProjectRequest = Pick<Project, 'userId'>;

type UpdateProjectRequest = Pick<Project,
| 'id'
| 'name'
>;
type UpdateProjectRequest = Pick<Project, 'id' | 'name'>;

app.post('/projects', async (c) => {
const body = await c.req.json<CreateProjectRequest>();
Expand Down
8 changes: 7 additions & 1 deletion apps/web/src/root.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { component$, useServerData, useStyles$ } from '@builder.io/qwik';
import { component$, useServerData, useStyles$, useVisibleTask$ } from '@builder.io/qwik';
import { RouterHead } from './components/base';

import styles from '@producktivity/ui/style.css?inline';
import { initFlowbite } from 'flowbite';

import { QwikCityProvider, RouterOutlet, ServiceWorkerRegister } from '@builder.io/qwik-city';

export default component$(() => {
useStyles$(styles);

useVisibleTask$(() => {
initFlowbite();
});

const nonce = useServerData<string | undefined>('nonce');

return (
Expand Down
13 changes: 10 additions & 3 deletions apps/web/src/routes/dashboard/[slug]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { Box } from '@producktivity/ui';
import { DashboardTab } from '../components/dashboard-tab';
import { ProjectTab } from '../components/project-tab';
import { DashboardTab } from '../components/dashboard/dashboard-tab';
import { ProjectTab } from '../components/project/project-tab';
import { TemplateTab } from '../components/template-tab';
import { useLocation } from '@builder.io/qwik-city';
import { routeLoader$, useLocation } from '@builder.io/qwik-city';
import { component$ } from '@builder.io/qwik';
import { ProjectFormProps } from '../components/project/create-project-modal';
import { type InitialValues } from '@modular-forms/qwik';

export const useFormLoader = routeLoader$<InitialValues<ProjectFormProps>>(() => ({
projectName: '',
templateId: '',
}));

export default component$(() => {
const loc = useLocation();
Expand Down
71 changes: 38 additions & 33 deletions apps/web/src/routes/dashboard/[slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { component$, useStore, $, Slot } from '@builder.io/qwik';
import { component$, useStore, $, Slot, useSignal, Fragment } from '@builder.io/qwik';
import { DocumentHead, useNavigate } from '@builder.io/qwik-city';
import { Box, Button, Text } from '@producktivity/ui';
import { generateSeoConfig } from '../../../configs/seo';
import { LuArrowUpCircle, LuPlusCircle } from '@qwikest/icons/lucide';
import { PlanBadge } from '../components/plan-badge';
import { useLocation } from '@builder.io/qwik-city';
import { CreateProjectModal } from '../components/project/create-project-modal';

interface DashboardTabsProps {
id: number;
Expand All @@ -19,6 +20,7 @@ const dashboardTabs: DashboardTabsProps[] = [
];

export default component$(() => {
const showSig = useSignal(false);
const loc = useLocation();
const currentActivePath = useStore({ path: '/' });
const nav = useNavigate();
Expand All @@ -29,40 +31,43 @@ export default component$(() => {
});

return (
<Box height="full-screen" width="full-screen" align="top-left">
<Box paddingY="2" paddingX="4" width="full" direction="horizontal" align="between-center">
<Box direction="horizontal" gap="1">
{dashboardTabs.map((item: DashboardTabsProps) => (
<Button rounded="full" variant={loc.params.slug === item.path ? 'primary' : 'secondary'} key={item.id} onClick$={() => handleSwitchTab(item.path)}>
<Text theme={loc.params.slug === item.path ? 'surface' : 'secondary'}>{item.label}</Text>
</Button>
))}
</Box>
<Button rounded="full">
<Box direction="horizontal" align="center" gap="0.5">
<Text theme="surface">
<LuPlusCircle />
</Text>
<Text theme="surface">Create new project</Text>
</Box>
</Button>
</Box>
<Box direction="horizontal" gap="0.5" paddingX="4">
<Text>Current Plan</Text>
<PlanBadge planType="Professional" />
<Button rounded="full" href="/pricing">
<Box direction="horizontal" align="center" gap="0.5">
<Text theme="surface">
<LuArrowUpCircle />
</Text>
<Text theme="surface" variant="small">
Upgrade
</Text>
<Fragment>
<Box width="full-screen" align="top-left">
<Box paddingY="2" paddingX="4" width="full" direction="horizontal" align="between-center">
<Box direction="horizontal" gap="1">
{dashboardTabs.map((item: DashboardTabsProps) => (
<Button rounded="full" variant={loc.params.slug === item.path ? 'primary' : 'secondary'} key={item.id} onClick$={() => handleSwitchTab(item.path)}>
<Text theme={loc.params.slug === item.path ? 'surface' : 'secondary'}>{item.label}</Text>
</Button>
))}
</Box>
</Button>
<Button rounded="full" onClick$={() => (showSig.value = true)}>
<Box direction="horizontal" align="center" gap="0.5">
<Text theme="surface">
<LuPlusCircle />
</Text>
<Text theme="surface">Create new project</Text>
</Box>
</Button>
</Box>
<Box direction="horizontal" gap="0.5" paddingX="4">
<Text>Current Plan</Text>
<PlanBadge planType="Professional" />
<Button rounded="full" href="/pricing">
<Box direction="horizontal" align="center" gap="0.5">
<Text theme="surface">
<LuArrowUpCircle />
</Text>
<Text theme="surface" variant="small">
Upgrade
</Text>
</Box>
</Button>
</Box>
<Slot />
</Box>
<Slot />
</Box>
<CreateProjectModal showModal={showSig} />
</Fragment>
);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,96 +1,12 @@
import { component$ } from '@builder.io/qwik';
import { Box, Text } from '@producktivity/ui';
import { Credit } from './credit';
import { Credit } from '../credit';
import { DashboardTable } from './dashboard-table';

export interface TaskMemberProps {
name: string;
}

export type TaskStatus = 'in progress' | 'failed' | 'success';

export interface TaskProps {
id: number;
title: string;
status: TaskStatus;
member: TaskMemberProps[];
createdWhen: Date;
finishedWhen?: Date;
}

const MockDashboardTasks: TaskProps[] = [
{
id: 0,
title: 'KMITL Volunteering',
status: 'failed',
createdWhen: new Date('02-11-2024'),
member: [
{
name: 'Boonpongkrong Narongrich',
},
],
finishedWhen: new Date('02-11-2024'),
},
{
id: 0,
title: 'KMITL Adhoc Staff',
status: 'failed',
createdWhen: new Date('02-17-2024'),
member: [
{
name: 'Sainan Anannarongdech',
},
],
finishedWhen: new Date('11-02-2024'),
},
{
id: 2,
title: 'IT Open house participants',
status: 'success',
createdWhen: new Date('03-21-2024'),
member: [
{
name: 'Rafah Pipatpong',
},
{
name: 'Sainan Anannarongdech',
},
{
name: 'Boonpradab Narongrich',
},
],
finishedWhen: new Date('03-21-2024'),
},
{
id: 3,
title: 'Tobe IT Bootcamp',
status: 'in progress',
createdWhen: new Date(),
member: [
{
name: 'Thitipat Pipatpong',
},
{
name: 'Boonnarong Kiatnakin',
},
],
},
{
id: 4,
title: 'Tobe IT Staff',
status: 'in progress',
createdWhen: new Date(),
member: [
{
name: 'Boonnarong Kiatnakin',
},
],
},
];
import { MockDashboardTasks } from '../../constant/mock-data';

export const DashboardTab = component$(() => {
return (
<Box paddingX="4" direction="horizontal" width="full" align="top">
<Box height="full-screen" paddingX="4" direction="horizontal" width="full" align="top">
<Box paddingX="4" paddingY="2" width="3/4" variant="surface" rounded="md">
<Box direction="horizontal" width="full" align="between-center">
<Box>
Expand Down
Loading
Loading