diff --git a/src/components/AssignedProjectCard.jsx b/src/components/AssignedProjectCard.jsx index 923d485..2ea47e5 100644 --- a/src/components/AssignedProjectCard.jsx +++ b/src/components/AssignedProjectCard.jsx @@ -91,7 +91,7 @@ export default function AssignedProjectCard({ project, onUnassign, showActions = )}
- + {showActions && onUnassign && ( + ) +} diff --git a/src/lib/lastLogin.js b/src/lib/lastLogin.js new file mode 100644 index 0000000..f1ba370 --- /dev/null +++ b/src/lib/lastLogin.js @@ -0,0 +1,10 @@ +import { formatViewLogTime } from './viewLog' + +// Letzter Portal-Login eines Kunden (Karte „Portal-Zugang“). Rein, unter Node testbar. + +/** ISO-Zeit -> "dd.mm.yyyy, hh:mm Uhr" in deutscher Zeit; ohne Login "noch nie". */ +export function formatLastLogin(iso) { + if (!iso) return 'noch nie' + const [day, time] = formatViewLogTime(iso).split(' ') + return `${day}, ${time} Uhr` +} diff --git a/src/pages/CustomerDetailPage.jsx b/src/pages/CustomerDetailPage.jsx index f34f02b..6402bb9 100644 --- a/src/pages/CustomerDetailPage.jsx +++ b/src/pages/CustomerDetailPage.jsx @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from 'react' import { useParams, Link, useNavigate, useSearchParams } from 'react-router-dom' -import { FaSpinner, FaStar, FaArrowLeft, FaFloppyDisk, FaArrowUp, FaKey, FaArrowUpRightFromSquare, FaBoxArchive, FaBoxOpen, FaTrash } from 'react-icons/fa6' +import { FaSpinner, FaStar, FaArrowLeft, FaFloppyDisk, FaArrowUp, FaKey, FaBoxArchive, FaBoxOpen, FaTrash } from 'react-icons/fa6' import { databases, DATABASE_ID, COLLECTIONS, Query } from '../lib/appwrite' import { PageHeader, Card, Button, Badge, Tabs, EmptyState, Field } from '../components/ui' import { StatusPill, UrgentPill } from '../components/ui/StatusPill' @@ -13,6 +13,9 @@ import { useWebsiteProjects } from '../hooks/useWebsiteProjects' import { customerTabs, resolveCustomerTab } from '../lib/customerTabs' import { customerStage, isArchived, isInvoiceReady, setCustomerArchived, upgradeToCustomer } from '../lib/leads' import CustomerViewLog from '../components/customer/CustomerViewLog' +import KundenansichtButton from '../components/customer/KundenansichtButton' +import { getCustomerPortalStatus } from '../lib/teamApi' +import { formatLastLogin } from '../lib/lastLogin' const PORTAL_URL = 'https://project.webklar.com' @@ -85,6 +88,7 @@ export default function CustomerDetailPage() { subtitle={[customer.location, customer.email, customer.phone].filter(Boolean).join(' · ')} actions={ <> + @@ -200,6 +204,15 @@ function PortalAccessCard({ customer, onSaved }) { const hasAccess = Boolean(customer.portalAccessEnabled && customer.appwriteUserId) const currentPassword = getCustomerPortalPassword(customer) + // Letzter Login kommt vom Portal (customerPortalAccess), nicht aus dem Kunden-Dokument + const [lastLogin, setLastLogin] = useState(undefined) + useEffect(() => { + let active = true + getCustomerPortalStatus(customer.$id) + .then((status) => active && setLastLogin(status.lastLoginAt || null)) + .catch(() => active && setLastLogin(false)) + return () => { active = false } + }, [customer.$id]) const savePassword = async () => { if (!customer.email) { @@ -232,6 +245,11 @@ function PortalAccessCard({ customer, onSaved }) { : kein Zugang}
+
+ Letzter Login + {lastLogin === undefined ? '…' : lastLogin === false ? 'nicht abrufbar' : formatLastLogin(lastLogin)} +
+ @@ -254,9 +272,7 @@ function PortalAccessCard({ customer, onSaved }) { - + {msg && {msg}}

diff --git a/src/pages/ProjectsPage.jsx b/src/pages/ProjectsPage.jsx index 99ee8d2..fe22b8c 100644 --- a/src/pages/ProjectsPage.jsx +++ b/src/pages/ProjectsPage.jsx @@ -574,7 +574,7 @@ export default function ProjectsPage() { ) : ( - + )} {hosted && ready && !project.archived && (