feat: hide certificate buttons for non-team members
- Added isTeamMember check (session user ID === certificate user ID) - Hide all action buttons (Download, Print, View Submission) for non-members - Hide "Back to Submission" button in header for non-members - Unauthenticated users and other users can view certificate but cannot interact with buttons 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
f5882e3cdc
commit
782cce820b
@@ -4,6 +4,7 @@ import { Button } from '@imphnen-frontend-service/ui/atoms';
|
|||||||
import { decodeCertificateId } from '../../../utils/certificate';
|
import { decodeCertificateId } from '../../../utils/certificate';
|
||||||
import {
|
import {
|
||||||
useCertificatePublicData,
|
useCertificatePublicData,
|
||||||
|
useAuthStore,
|
||||||
} from '@imphnen-frontend-service/service';
|
} from '@imphnen-frontend-service/service';
|
||||||
import QRCode from 'qrcode';
|
import QRCode from 'qrcode';
|
||||||
import html2canvas from 'html2canvas';
|
import html2canvas from 'html2canvas';
|
||||||
@@ -17,6 +18,7 @@ interface DecodedCert {
|
|||||||
const CertificatePage: FC = (): ReactElement => {
|
const CertificatePage: FC = (): ReactElement => {
|
||||||
const { certId } = useParams<{ certId: string }>();
|
const { certId } = useParams<{ certId: string }>();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { session } = useAuthStore();
|
||||||
const [decodedInfo, setDecodedInfo] = useState<DecodedCert | null>(null);
|
const [decodedInfo, setDecodedInfo] = useState<DecodedCert | null>(null);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const teamNameRef = useRef<HTMLHeadingElement>(null);
|
const teamNameRef = useRef<HTMLHeadingElement>(null);
|
||||||
@@ -74,6 +76,9 @@ const CertificatePage: FC = (): ReactElement => {
|
|||||||
// Certificate name from the user data
|
// Certificate name from the user data
|
||||||
const certificateName = certificateUser?.fullname;
|
const certificateName = certificateUser?.fullname;
|
||||||
|
|
||||||
|
// Check if current user is viewing their own certificate (team member)
|
||||||
|
const isTeamMember = session?.user?.id === decodedInfo?.userId;
|
||||||
|
|
||||||
// Dynamic font sizing: shrink by 2px if height exceeds 80px
|
// Dynamic font sizing: shrink by 2px if height exceeds 80px
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const adjustFontSize = (
|
const adjustFontSize = (
|
||||||
@@ -281,7 +286,7 @@ const CertificatePage: FC = (): ReactElement => {
|
|||||||
{team?.name}
|
{team?.name}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{team && (
|
{team && isTeamMember && (
|
||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -472,35 +477,37 @@ const CertificatePage: FC = (): ReactElement => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Actions */}
|
{/* Actions */}
|
||||||
<div className="bg-gray-50 dark:bg-gray-800 p-6 grid grid-cols-2 xl:grid-cols-3 gap-3 justify-center no-print">
|
{isTeamMember && (
|
||||||
<Button
|
<div className="bg-gray-50 dark:bg-gray-800 p-6 grid grid-cols-2 xl:grid-cols-3 gap-3 justify-center no-print">
|
||||||
variant="secondary"
|
|
||||||
onClick={handleDownloadCertificate}
|
|
||||||
className="flex items-center gap-2"
|
|
||||||
disabled={isGenerating}
|
|
||||||
>
|
|
||||||
{isGenerating ? '⏳ Generating...' : '📥 Download'}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
onClick={handlePrintCertificate}
|
|
||||||
className="flex items-center gap-2"
|
|
||||||
disabled={isGenerating}
|
|
||||||
>
|
|
||||||
{isGenerating ? '⏳ Generating...' : '🖨️ Print'}
|
|
||||||
</Button>
|
|
||||||
{team && (
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() =>
|
|
||||||
navigate(`/teams/${team.id}/submission`)
|
|
||||||
}
|
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
className="col-span-2 flex items-center gap-2 xl:col-span-1"
|
onClick={handleDownloadCertificate}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
disabled={isGenerating}
|
||||||
>
|
>
|
||||||
View Submission
|
{isGenerating ? '⏳ Generating...' : '📥 Download'}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
<Button
|
||||||
</div>
|
variant="secondary"
|
||||||
|
onClick={handlePrintCertificate}
|
||||||
|
className="flex items-center gap-2"
|
||||||
|
disabled={isGenerating}
|
||||||
|
>
|
||||||
|
{isGenerating ? '⏳ Generating...' : '🖨️ Print'}
|
||||||
|
</Button>
|
||||||
|
{team && (
|
||||||
|
<Button
|
||||||
|
onClick={() =>
|
||||||
|
navigate(`/teams/${team.id}/submission`)
|
||||||
|
}
|
||||||
|
variant="secondary"
|
||||||
|
className="col-span-2 flex items-center gap-2 xl:col-span-1"
|
||||||
|
>
|
||||||
|
View Submission
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Info Box */}
|
{/* Info Box */}
|
||||||
|
|||||||
Reference in New Issue
Block a user