feat: pyush

This commit is contained in:
Maulana Sodiqin
2025-11-30 22:43:09 +07:00
parent 6bbc87479a
commit 0c646ceb85
4 changed files with 103 additions and 22 deletions
+16
View File
@@ -11,6 +11,9 @@ import { Button } from '@imphnen-frontend-service/ui/atoms';
import { Icon } from '@iconify/react';
import ProfilePage from '../profile/page';
// Team features deadline: 2025-11-30 23:59:00 WIB (UTC+7)
const TEAM_FEATURES_DEADLINE = new Date('2025-11-30T16:59:00Z');
type Invitation = {
id: string;
team: {
@@ -34,6 +37,9 @@ type Invitation = {
const DashboardPage: FC = (): ReactElement => {
const { session } = useAuthStore();
const [showProfileModal, setShowProfileModal] = useState(false);
// Check if team features are closed
const isTeamFeaturesClosed = new Date() >= TEAM_FEATURES_DEADLINE;
// Lock background scroll when profile modal is open
useEffect(() => {
if (showProfileModal) {
@@ -93,6 +99,14 @@ const DashboardPage: FC = (): ReactElement => {
<h2 className="text-xl font-bold text-gray-900 dark:text-white mb-4">
Team Invitations ({invitations.length})
</h2>
{isTeamFeaturesClosed && (
<div className="mb-4 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-lg p-3">
<p className="text-sm text-amber-700 dark:text-amber-300 flex items-center gap-2">
<Icon icon="mdi:clock-alert" className="text-lg shrink-0" />
Team features are closed. You can no longer accept invitations.
</p>
</div>
)}
<div className="space-y-3 font-sans">
{invitations.map((invitation) => (
<div
@@ -108,6 +122,7 @@ const DashboardPage: FC = (): ReactElement => {
{invitation.inviter?.fullname ?? 'Unknown User'}
</p>
</div>
{!isTeamFeaturesClosed && (
<div className="flex space-x-2">
<Button
size="sm"
@@ -123,6 +138,7 @@ const DashboardPage: FC = (): ReactElement => {
Decline
</Button>
</div>
)}
</div>
))}
</div>
+12 -6
View File
@@ -17,6 +17,9 @@ import { Icon } from '@iconify/react';
const MAX_TEAM_MEMBERS = 5;
// Team features deadline: 2025-11-30 23:59:00 WIB (UTC+7)
const TEAM_FEATURES_DEADLINE = new Date('2025-11-30T16:59:00Z');
// Image component with loading state
const ImageWithLoader: FC<{
src: string;
@@ -52,6 +55,9 @@ const TeamDashboardPage: FC = (): ReactElement => {
const { teamId } = useParams<{ teamId: string }>();
const navigate = useNavigate();
const { session } = useAuthStore();
// Check if team features are closed
const isTeamFeaturesClosed = new Date() >= TEAM_FEATURES_DEADLINE;
const [showInviteModal, setShowInviteModal] = useState(false);
const [showJoinRequestsModal, setShowJoinRequestsModal] = useState(false);
const [showLeaveModal, setShowLeaveModal] = useState(false);
@@ -369,8 +375,8 @@ const TeamDashboardPage: FC = (): ReactElement => {
Team Management
</h2>
<div className="grid gap-3 sm:grid-cols-2">
{/* Hide invite/join management after submission */}
{!team.has_submission && (
{/* Hide invite/join management after submission or deadline */}
{!team.has_submission && !isTeamFeaturesClosed && (
<>
<Button
className="w-full"
@@ -397,7 +403,7 @@ const TeamDashboardPage: FC = (): ReactElement => {
</Button>
</>
)}
{!team.has_submission && (
{!team.has_submission && !isTeamFeaturesClosed && (
<Link to={`/teams/${teamId}/edit`}>
<Button className="w-full" variant="secondary">
<Icon icon="mdi:pencil" className="inline-block mr-2" />
@@ -441,8 +447,8 @@ const TeamDashboardPage: FC = (): ReactElement => {
Maximum team size reached ({MAX_TEAM_MEMBERS} members)
</p>
)}
{/* Danger Zone - Only show when leader is alone and no submission */}
{members.length === 1 && !team.has_submission && (
{/* Danger Zone - Only show when leader is alone, no submission, and features not closed */}
{members.length === 1 && !team.has_submission && !isTeamFeaturesClosed && (
<div className="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
<h3 className="text-sm font-medium text-red-600 dark:text-red-400 mb-3">
Danger Zone
@@ -480,7 +486,7 @@ const TeamDashboardPage: FC = (): ReactElement => {
</Button>
</Link>
)}
{!team.has_submission && (
{!team.has_submission && !isTeamFeaturesClosed && (
<Button
className="w-full bg-red-600 hover:bg-red-700 text-white"
onClick={() => setShowLeaveModal(true)}
+8 -1
View File
@@ -17,6 +17,9 @@ import { Icon } from '@iconify/react';
const DEFAULT_PER_PAGE = 12;
const PER_PAGE_OPTIONS = [6, 12, 24, 48];
// Team features deadline: 2025-11-30 23:59:00 WIB (UTC+7)
const TEAM_FEATURES_DEADLINE = new Date('2025-11-30T16:59:00Z');
// Member filter options
const MEMBER_FILTER_OPTIONS = [
{ label: 'All Teams', value: '', minMembers: undefined, maxMembers: undefined },
@@ -57,6 +60,9 @@ const BrowseTeamsPage: FC = (): ReactElement => {
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
// Check if team features are closed
const isTeamFeaturesClosed = new Date() >= TEAM_FEATURES_DEADLINE;
// Initialize state from URL params
const initialPage = parseInt(searchParams.get('page') || '1', 10);
const initialPerPage = parseInt(
@@ -416,7 +422,8 @@ const BrowseTeamsPage: FC = (): ReactElement => {
<>
{myTeams.length === 0 &&
(team.member_count || 0) < 5 &&
!team.has_submission && (
!team.has_submission &&
!isTeamFeaturesClosed && (
<Button
className="w-full"
onClick={() => handleJoinRequest(team.id)}
@@ -6,13 +6,21 @@ import { useForm, Controller } from 'react-hook-form';
import { teamCreateSchema, TTeamCreateForm, useCreateTeam, ETeamVisibility, useUploadFile } from '@imphnen-frontend-service/service';
import { zodResolver } from '@hookform/resolvers/zod';
import { toast } from 'sonner';
import { Icon } from '@iconify/react';
import { CitySelect } from '../../../components/city-select';
const MAX_FILE_SIZE = 2 * 1024 * 1024; // 2MB
// Team features deadline: 2025-11-30 23:59:00 WIB (UTC+7)
const TEAM_FEATURES_DEADLINE = new Date('2025-11-30T16:59:00Z');
const CreateTeamPage: FC = (): ReactElement => {
const navigate = useNavigate();
// Check if team features are closed
const isTeamFeaturesClosed = new Date() >= TEAM_FEATURES_DEADLINE;
const [logoFile, setLogoFile] = useState<File | null>(null);
const [logoPreview, setLogoPreview] = useState<string>('');
const [bannerFile, setBannerFile] = useState<File | null>(null);
@@ -103,6 +111,50 @@ const CreateTeamPage: FC = (): ReactElement => {
}
});
// Show closed screen if team features are closed
if (isTeamFeaturesClosed) {
return (
<div className="flex justify-center items-center min-h-screen bg-gray-50 dark:bg-gray-950 p-4">
<div className="bg-white dark:bg-gray-900 w-full max-w-md p-8 rounded-2xl shadow-lg border border-gray-200 dark:border-gray-700 text-center">
<div className="mb-6">
<div className="mx-auto w-16 h-16 bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center mb-4">
<Icon
icon="mdi:clock-alert"
className="text-3xl text-red-600 dark:text-red-400"
/>
</div>
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">
Team Features Closed
</h2>
<p className="text-gray-600 dark:text-gray-400">
Team creation is no longer available.
</p>
</div>
<div className="space-y-4">
<p className="text-sm text-gray-600 dark:text-gray-400">
The deadline for team features was November 30, 2025 at 23:59 WIB.
</p>
<button
onClick={() => navigate('/dashboard')}
className="w-full py-3 bg-primary-600 text-white rounded-lg font-semibold hover:bg-primary-700 transition-colors cursor-pointer"
>
Back to Dashboard
</button>
<button
onClick={() => navigate('/teams/browse')}
className="w-full py-3 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white transition-colors cursor-pointer"
>
Browse Teams
</button>
</div>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-50 dark:bg-neutral-950">
{/* Header */}