feat(ui): separate career and connected accounts
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
|
||||
import { Alert, Box, Paper, Typography } from "@mui/material";
|
||||
|
||||
import ProfilePage from "./ProfilePage";
|
||||
|
||||
export default function CareerWorkspacePage() {
|
||||
return (
|
||||
<Box sx={{ display: "grid", gap: 2 }}>
|
||||
<Paper sx={{ p: 2.5, borderRadius: 4, boxShadow: "0px 8px 24px -12px rgba(15,23,42,0.12)" }}>
|
||||
<Typography variant="h5" sx={{ fontWeight: 900, mb: 0.5 }}>Career Workspace</Typography>
|
||||
<Typography sx={{ color: "text.secondary" }}>
|
||||
Maintain the master career profile that powers your CVs, tailored application material, and future portfolio outputs.
|
||||
</Typography>
|
||||
</Paper>
|
||||
<Alert severity="info" sx={{ borderRadius: 3 }}>
|
||||
Your master profile is the source of truth. Job-specific CV drafts remain separate and never overwrite it.
|
||||
</Alert>
|
||||
<ProfilePage careerOnly />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
|
||||
import { Box, Button, Paper, Typography } from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import EmailProviderConnections from "../components/EmailProviderConnections";
|
||||
|
||||
export default function ConnectedAccountsPage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "grid", gap: 2 }}>
|
||||
<Paper sx={{ p: 2.5, borderRadius: 4, boxShadow: "0px 8px 24px -12px rgba(15,23,42,0.12)" }}>
|
||||
<Typography variant="h5" sx={{ fontWeight: 900, mb: 0.5 }}>Connected accounts</Typography>
|
||||
<Typography sx={{ color: "text.secondary", maxWidth: 720 }}>
|
||||
Connect the inboxes Jobbjakt may use to identify recruiter correspondence. Connecting an inbox never sends a message on your behalf.
|
||||
</Typography>
|
||||
<Button sx={{ mt: 1 }} onClick={() => navigate("/settings")}>Back to settings</Button>
|
||||
</Paper>
|
||||
<EmailProviderConnections />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -13,7 +13,6 @@ import MicrosoftAuthCard from "../components/MicrosoftAuthCard";
|
||||
import AuthStatusCard from "../components/AuthStatusCard";
|
||||
import TwoFactorSettingsCard from "../components/TwoFactorSettingsCard";
|
||||
import SessionsSettingsCard from "../components/SessionsSettingsCard";
|
||||
import EmailProviderConnections from "../components/EmailProviderConnections";
|
||||
import CropImageDialog from "../components/CropImageDialog";
|
||||
import { useToast } from "../toast";
|
||||
import { useI18n } from "../i18n/I18nProvider";
|
||||
@@ -227,7 +226,7 @@ function FieldReviewNote({ metadata }: { metadata?: StructuredCvFieldMetadata })
|
||||
);
|
||||
}
|
||||
|
||||
export default function ProfilePage() {
|
||||
export default function ProfilePage({ careerOnly = false }: { careerOnly?: boolean }) {
|
||||
const { toast } = useToast();
|
||||
const { t } = useI18n();
|
||||
const cvInputRef = useRef<HTMLInputElement | null>(null);
|
||||
@@ -553,7 +552,7 @@ export default function ProfilePage() {
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography variant="h5" sx={{ fontWeight: 900 }}>
|
||||
{t("profileTitle")}
|
||||
{careerOnly ? "Master career profile" : t("profileTitle")}
|
||||
</Typography>
|
||||
<Typography sx={{ color: "text.secondary" }}>{me?.userName || me?.displayName || fullName || me?.email || "-"}</Typography>
|
||||
<Typography variant="body2" sx={{ color: "text.secondary" }}>{headline || t("profileHeadlinePlaceholder")}</Typography>
|
||||
@@ -566,37 +565,38 @@ export default function ProfilePage() {
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<AuthStatusCard />
|
||||
<GoogleAuthCard />
|
||||
<MicrosoftAuthCard />
|
||||
<Box sx={{ mt: 2 }}>
|
||||
<EmailProviderConnections />
|
||||
</Box>
|
||||
{!careerOnly ? <>
|
||||
<AuthStatusCard />
|
||||
<GoogleAuthCard />
|
||||
<MicrosoftAuthCard />
|
||||
</> : null}
|
||||
|
||||
<Box sx={{ mt: 3, display: "grid", gridTemplateColumns: { xs: "1fr", md: "1fr 1fr" }, gap: 2 }}>
|
||||
<Box sx={{ gridColumn: "1 / -1" }}>
|
||||
{!careerOnly ? <Box sx={{ gridColumn: "1 / -1" }}>
|
||||
<Typography variant="h6">{t("profileAccountSection")}</Typography>
|
||||
{!isLocal ? (
|
||||
<Alert severity="info" sx={{ mt: 1 }}>
|
||||
{t("profileReadOnlyInfo")}
|
||||
</Alert>
|
||||
) : null}
|
||||
</Box>
|
||||
</Box> : null}
|
||||
|
||||
<TextField label={t("profileDisplayName")} value={displayName} onChange={(e) => setDisplayName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileUsername")} value={userName} onChange={(e) => setUserName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileFirstName")} value={firstName} onChange={(e) => setFirstName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileLastName")} value={lastName} onChange={(e) => setLastName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileEmail")} value={email} onChange={(e) => setEmail(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField
|
||||
{!careerOnly ? <>
|
||||
<TextField label={t("profileDisplayName")} value={displayName} onChange={(e) => setDisplayName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileUsername")} value={userName} onChange={(e) => setUserName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileFirstName")} value={firstName} onChange={(e) => setFirstName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileLastName")} value={lastName} onChange={(e) => setLastName(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileEmail")} value={email} onChange={(e) => setEmail(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField
|
||||
label={t("profileHeadline")}
|
||||
value={headline}
|
||||
onChange={(e) => setHeadline(e.target.value)}
|
||||
helperText={t("profileHeadlineHelp")}
|
||||
fullWidth
|
||||
/>
|
||||
/>
|
||||
</> : null}
|
||||
|
||||
<Box sx={{ gridColumn: "1 / -1", p: 2, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default" }}>
|
||||
<Box sx={{ gridColumn: "1 / -1", p: 2, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default", display: careerOnly ? "block" : "none" }}>
|
||||
<Box sx={{ display: "flex", justifyContent: "space-between", gap: 2, flexWrap: "wrap", alignItems: "center", mb: 1.5 }}>
|
||||
<Box>
|
||||
<Typography variant="h6">{t("profileMasterCv")}</Typography>
|
||||
@@ -1318,16 +1318,17 @@ export default function ProfilePage() {
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ gridColumn: "1 / -1", mt: 1 }}>
|
||||
{!careerOnly ? <Box sx={{ gridColumn: "1 / -1", mt: 1 }}>
|
||||
<Divider sx={{ mb: 2 }} />
|
||||
<Typography variant="h6">{t("profileChangePassword")}</Typography>
|
||||
{!isLocal ? <Typography sx={{ color: "text.secondary" }}>{t("profilePasswordLocalOnly")}</Typography> : null}
|
||||
</Box>
|
||||
</Box> : null}
|
||||
|
||||
<TextField label={t("profileCurrentPassword")} type="password" value={currentPassword} onChange={(e) => setCurrentPassword(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileNewPassword")} type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
{!careerOnly ? <>
|
||||
<TextField label={t("profileCurrentPassword")} type="password" value={currentPassword} onChange={(e) => setCurrentPassword(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
<TextField label={t("profileNewPassword")} type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} disabled={!isLocal} fullWidth />
|
||||
|
||||
<Box sx={{ gridColumn: "1 / -1", display: "flex", justifyContent: "flex-end" }}>
|
||||
<Box sx={{ gridColumn: "1 / -1", display: "flex", justifyContent: "flex-end" }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
disabled={!isLocal || loading}
|
||||
@@ -1348,11 +1349,12 @@ export default function ProfilePage() {
|
||||
>
|
||||
{t("profileUpdatePassword")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</> : null}
|
||||
</Box>
|
||||
|
||||
{isLocal ? <TwoFactorSettingsCard /> : null}
|
||||
{isLocal ? <SessionsSettingsCard /> : null}
|
||||
{!careerOnly && isLocal ? <TwoFactorSettingsCard /> : null}
|
||||
{!careerOnly && isLocal ? <SessionsSettingsCard /> : null}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user