diff --git a/apps/backoffice/src/app/(protected)/hackathon-submissions/page.tsx b/apps/backoffice/src/app/(protected)/hackathon-submissions/page.tsx index 1099a2c..ea8a53b 100644 --- a/apps/backoffice/src/app/(protected)/hackathon-submissions/page.tsx +++ b/apps/backoffice/src/app/(protected)/hackathon-submissions/page.tsx @@ -1,7 +1,4 @@ import { FC, ReactElement, useState } from 'react'; -import ModalUserDetail from '../../../components/modal-user-detail'; -import ModalSuspendOrBan from '../../../components/modal-suspend-or-ban'; -import ModalDeleteUser from '../../../components/modal-delete-user'; import { BackofficeWrapper, DataTable, @@ -16,13 +13,9 @@ import { } from '@tanstack/react-table'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { cn } from '@imphnen-frontend-service/utils'; -import { SearchOutlined } from '@ant-design/icons'; +import { EditOutlined } from '@ant-design/icons'; export const HackathonUsersPage: FC = (): ReactElement => { - const [showDeleteModal, setShowDeleteModal] = useState(false); - const [showDetailModal, setShowDetailModal] = useState(false); - const [showSuspendModal, setShowSuspendModal] = useState(false); - const [rowSelection, setRowSelection] = useState({}); const [pagination, setPagination] = useState({ pageIndex: 0, @@ -31,80 +24,38 @@ export const HackathonUsersPage: FC = (): ReactElement => { const mockData: any[] = Array.from({ length: 90 }, (_, i) => ({ id: i + 1, - name: i % 3 === 0 ? 'Ahmad Wijuana' : 'Sofia Wijuana', - email: 'fullname23@gmail.com', - rating: 4.5, - status: i % 2 === 0 ? 'active' : 'inactive', + project_name: `Project ${i + 1}`, + repository_url: `https://github.com/user/repo${i + 1}`, + demo_url: `https://demo.example.com/project${i + 1}`, + presentation_url: `https://slides.example.com/project${i + 1}`, })); type UserStatus = 'active' | 'inactive'; - interface UserType { + interface SubmissionType { id: number; - name: string; - email: string; - rating: number; - status: UserStatus; + project_name: string; + repository_url: string; + demo_url: string; + presentation_url: string; } - const columns: ColumnDef[] = [ + const columns: ColumnDef[] = [ { - id: 'select', - meta: { cellClassName: cn('w-20') }, - header: ({ table }) => ( - - ), - cell: ({ row }) => ( - - ), + header: 'Project Name', + accessorKey: 'project_name', }, { - id: 'name', - header: 'Name', - accessorKey: 'name', + header: 'Repository URL', + accessorKey: 'repository_url', }, { - id: 'email', - header: 'Email', - accessorKey: 'email', + header: 'Demo URL', + accessorKey: 'demo_url', }, { - id: 'rating', - header: 'Rating', - accessorKey: 'rating', - }, - { - id: 'status', - header: 'Status', - accessorKey: 'status', - cell: ({ row }) => { - const status = row.original.status; - const statusColors: Record = { - active: 'bg-success-200 text-success-500', - inactive: 'bg-danger-200 text-danger-500', - }; - const statusText: Record = { - active: 'Active', - inactive: 'Inactive', - }; - return ( -
- {statusText[status]} -
- ); - }, + header: 'Presentation URL', + accessorKey: 'presentation_url', }, { header: 'Action', @@ -113,17 +64,12 @@ export const HackathonUsersPage: FC = (): ReactElement => { ), }, @@ -175,18 +121,6 @@ export const HackathonUsersPage: FC = (): ReactElement => { {/* Modals extracted into shared backoffice components */} - setShowDetailModal(false)} - /> - setShowSuspendModal(false)} - /> - setShowDeleteModal(false)} - /> ); }; diff --git a/apps/backoffice/src/app/(protected)/hackathon-teams/page.tsx b/apps/backoffice/src/app/(protected)/hackathon-teams/page.tsx index 9efec8e..eb52968 100644 --- a/apps/backoffice/src/app/(protected)/hackathon-teams/page.tsx +++ b/apps/backoffice/src/app/(protected)/hackathon-teams/page.tsx @@ -1,7 +1,4 @@ import { FC, ReactElement, useState } from 'react'; -import ModalUserDetail from '../../../components/modal-user-detail'; -import ModalSuspendOrBan from '../../../components/modal-suspend-or-ban'; -import ModalDeleteUser from '../../../components/modal-delete-user'; import { BackofficeWrapper, DataTable, @@ -16,11 +13,11 @@ import { } from '@tanstack/react-table'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { cn } from '@imphnen-frontend-service/utils'; +import { useTeams } from '@imphnen-frontend-service/service'; +import { EditOutlined } from '@ant-design/icons'; export const HackathonTeamsPage: FC = (): ReactElement => { - const [showDeleteModal, setShowDeleteModal] = useState(false); - const [showDetailModal, setShowDetailModal] = useState(false); - const [showSuspendModal, setShowSuspendModal] = useState(false); + const { data: teamsData } = useTeams(); const [rowSelection, setRowSelection] = useState({}); const [pagination, setPagination] = useState({ @@ -64,34 +61,12 @@ export const HackathonTeamsPage: FC = (): ReactElement => { const columns: ColumnDef[] = [ { - id: 'select', - meta: { cellClassName: cn('w-12') }, - header: ({ table }) => ( - - ), - cell: ({ row }) => ( - - ), + accessorKey: 'id', + header: 'ID', }, { accessorKey: 'name', header: 'Team Name', - cell: ({ row }) => ( -
-
{row.original.name}
-
{row.original.id}
-
- ), }, { accessorKey: 'city', @@ -105,10 +80,10 @@ export const HackathonTeamsPage: FC = (): ReactElement => { return ( {isPublic ? 'Public' : 'Private'} @@ -119,12 +94,6 @@ export const HackathonTeamsPage: FC = (): ReactElement => { { accessorKey: 'member_count', header: 'Members', - cell: ({ row }) => ( -
- {row.getValue('member_count')} - members -
- ), }, { id: 'leader', @@ -139,22 +108,22 @@ export const HackathonTeamsPage: FC = (): ReactElement => {
{leader.email}
) : ( - No leader + - ); }, }, { accessorKey: 'has_submission', - header: 'Submission', + header: 'Submitted', cell: ({ row }) => { const hasSubmission = row.original.has_submission; return ( {hasSubmission ? 'Yes' : 'No'} @@ -166,11 +135,7 @@ export const HackathonTeamsPage: FC = (): ReactElement => { accessorKey: 'updated_at', header: 'Last Updated', cell: ({ row }) => { - return ( - - {new Date(row.original.updated_at).toLocaleDateString()} - - ); + return new Date(row.original.updated_at).toLocaleDateString(); }, }, { @@ -180,25 +145,14 @@ export const HackathonTeamsPage: FC = (): ReactElement => { cell: ({ row }) => (
- | -
), @@ -249,18 +203,6 @@ export const HackathonTeamsPage: FC = (): ReactElement => { {/* Modals extracted into shared backoffice components */} - setShowDetailModal(false)} - /> - setShowSuspendModal(false)} - /> - setShowDeleteModal(false)} - /> ); }; diff --git a/apps/backoffice/src/components/modal-user-detail.tsx b/apps/backoffice/src/app/(protected)/hackathon-users/_components/modal-user-detail.tsx similarity index 95% rename from apps/backoffice/src/components/modal-user-detail.tsx rename to apps/backoffice/src/app/(protected)/hackathon-users/_components/modal-user-detail.tsx index 57aadf2..dd0a304 100644 --- a/apps/backoffice/src/components/modal-user-detail.tsx +++ b/apps/backoffice/src/app/(protected)/hackathon-users/_components/modal-user-detail.tsx @@ -14,7 +14,7 @@ const ModalUserDetail: FC = ({ isOpen, onClose }) => {

User Detail

-
diff --git a/apps/backoffice/src/app/(protected)/hackathon-users/page.tsx b/apps/backoffice/src/app/(protected)/hackathon-users/page.tsx index 8cb3ab1..c9a51ec 100644 --- a/apps/backoffice/src/app/(protected)/hackathon-users/page.tsx +++ b/apps/backoffice/src/app/(protected)/hackathon-users/page.tsx @@ -1,7 +1,5 @@ import { FC, ReactElement, useState } from 'react'; -import ModalUserDetail from '../../../components/modal-user-detail'; -import ModalSuspendOrBan from '../../../components/modal-suspend-or-ban'; -import ModalDeleteUser from '../../../components/modal-delete-user'; +import ModalUserDetail from './_components/modal-user-detail'; import { BackofficeWrapper, DataTable, @@ -16,12 +14,11 @@ import { } from '@tanstack/react-table'; import { Button } from '@imphnen-frontend-service/ui/atoms'; import { cn } from '@imphnen-frontend-service/utils'; -import { SearchOutlined } from '@ant-design/icons'; +import { EditOutlined } from '@ant-design/icons'; +// Removed unused SearchOutlined icon after schema revision export const HackathonUsersPage: FC = (): ReactElement => { - const [showDeleteModal, setShowDeleteModal] = useState(false); const [showDetailModal, setShowDetailModal] = useState(false); - const [showSuspendModal, setShowSuspendModal] = useState(false); const [rowSelection, setRowSelection] = useState({}); const [pagination, setPagination] = useState({ @@ -29,82 +26,68 @@ export const HackathonUsersPage: FC = (): ReactElement => { pageSize: 9, }); - const mockData: any[] = Array.from({ length: 90 }, (_, i) => ({ - id: i + 1, - name: i % 3 === 0 ? 'Ahmad Wijuana' : 'Sofia Wijuana', - email: 'fullname23@gmail.com', - rating: 4.5, - status: i % 2 === 0 ? 'active' : 'inactive', - })); - - type UserStatus = 'active' | 'inactive'; - + // Mock data aligned to API user schema interface UserType { - id: number; - name: string; + id: string; + fullname: string; email: string; - rating: number; - status: UserStatus; + is_active: boolean; + location: string; + created_at: string; + updated_at: string; + avatar?: string; + phone_number?: string; } + const mockData: UserType[] = Array.from({ length: 50 }, (_, i) => ({ + id: `24db9e4d-ca4c-46aa-ac36-8ef04bbe015f`, + fullname: i % 3 === 0 ? 'Ahmad Wijuana' : 'Sofia Wijuana', + email: `user${i + 1}@example.com`, + is_active: i % 5 !== 0, + location: i % 2 === 0 ? 'Jakarta' : 'Bandung', + created_at: new Date(Date.now() - i * 86400000).toISOString(), + updated_at: new Date().toISOString(), + avatar: undefined, + phone_number: '+62-812-0000-000', + })); + const columns: ColumnDef[] = [ { - id: 'select', - meta: { cellClassName: cn('w-20') }, - header: ({ table }) => ( - - ), - cell: ({ row }) => ( - - ), + accessorKey: 'id', + header: 'ID', }, { - id: 'name', - header: 'Name', - accessorKey: 'name', + accessorKey: 'fullname', + header: 'Full Name', }, { - id: 'email', - header: 'Email', accessorKey: 'email', + header: 'Email', }, { - id: 'rating', - header: 'Rating', - accessorKey: 'rating', + accessorKey: 'location', + header: 'Location', }, { - id: 'status', + accessorKey: 'is_active', header: 'Status', - accessorKey: 'status', - cell: ({ row }) => { - const status = row.original.status; - const statusColors: Record = { - active: 'bg-success-200 text-success-500', - inactive: 'bg-danger-200 text-danger-500', - }; - const statusText: Record = { - active: 'Active', - inactive: 'Inactive', - }; - return ( -
- {statusText[status]} -
- ); - }, + cell: ({ row }) => ( +
+ {row.original.is_active ? 'Active' : 'Inactive'} +
+ ), + }, + { + accessorKey: 'created_at', + header: 'Joined', + cell: ({ row }) => new Date(row.original.created_at).toLocaleDateString(), }, { header: 'Action', @@ -113,17 +96,12 @@ export const HackathonUsersPage: FC = (): ReactElement => { ), }, @@ -161,10 +139,10 @@ export const HackathonUsersPage: FC = (): ReactElement => { @@ -174,19 +152,11 @@ export const HackathonUsersPage: FC = (): ReactElement => { - {/* Modals extracted into shared backoffice components */} + {/* Modals component */} setShowDetailModal(false)} /> - setShowSuspendModal(false)} - /> - setShowDeleteModal(false)} - /> ); }; diff --git a/apps/backoffice/src/components/modal-delete-user.tsx b/apps/backoffice/src/components/modal-delete-user.tsx deleted file mode 100644 index f592091..0000000 --- a/apps/backoffice/src/components/modal-delete-user.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { FC } from 'react'; - -interface ModalProps { - isOpen: boolean; - onClose: () => void; -} - -const ModalDeleteUser: FC = ({ isOpen, onClose }) => { - if (!isOpen) return null; - return ( -
-
-
-
-
-

Delete User

- -
-
-

- Are you sure you want to delete this user? This action cannot be - undone. -

-
- - -
-
-
-
-
- ); -}; - -export default ModalDeleteUser; diff --git a/apps/backoffice/src/components/modal-suspend-or-ban.tsx b/apps/backoffice/src/components/modal-suspend-or-ban.tsx deleted file mode 100644 index 517685d..0000000 --- a/apps/backoffice/src/components/modal-suspend-or-ban.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { FC } from 'react'; - -interface ModalProps { - isOpen: boolean; - onClose: () => void; -} - -const ModalSuspendOrBan: FC = ({ isOpen, onClose }) => { - if (!isOpen) return null; - return ( -
-
-
-
-
-

Suspend or Ban User

- -
-
- -