sozsoft-platform/configs/seeds/data/App.DeveloperKit.CustomComponents/23744edc-eda9-512e-8079-fe2e8e5fd2a8.json
2026-10-05 15:58:59 +03:00

29 lines
7.9 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"ListFormCode": "App.DeveloperKit.CustomComponents",
"KeyFieldName": "Id",
"GeneratedAt": "2026-10-04T15:00:00Z",
"Order": 0,
"Rows": [
{
"Id": "23744edc-eda9-512e-8079-fe2e8e5fd2a8",
"Name": "MyLeaveWidget",
"RoutePath": null,
"Description": "Intranet panosu: çalışanın izin bakiyesi, süren talepleri ve izin talebi/taleplerim/bakiyem bağlantıları",
"IsActive": true,
"Dependencies": [],
"Code": "// Calisanin kendi izin ozeti. Veri ekranlarin kendi sorgusundan okunur: satir suzmesi\n// (EmployeeId = oturum acan kullanici) ve yetki ListForm'da kalir, bilesen yalnizca toplar.\nconst REQUESTS = 'App.Hr.MyLeaveRequest'\nconst BALANCE = 'App.Hr.MyLeaveBalance'\nconst OPEN_STATUSES = ['Onaya Gönderildi', 'Müdür Onayı', 'İK Onayı']\n\nconst loadRows = async (listFormCode) => {\n const response = await apiService.fetchData({\n method: 'GET',\n url: '/api/app/list-form-select/select',\n params: { listFormCode, take: 500 },\n })\n return response.data?.data ?? []\n}\n\nconst formatDays = (value) => {\n const number = Number(value ?? 0)\n return Number.isInteger(number) ? String(number) : number.toFixed(1)\n}\n\nconst formatDate = (value) => {\n if (!value) return '-'\n const [year, month, day] = String(value).slice(0, 10).split('-')\n return `${day}.${month}.${year}`\n}\n\nconst Stat = ({ label, value, className }) => (\n <div className=\"rounded-lg border border-gray-200 bg-gray-50 p-2 text-center dark:border-gray-700 dark:bg-gray-900/40\">\n <div className={'text-lg font-semibold ' + className}>{value}</div>\n <div className=\"truncate text-xs text-gray-500 dark:text-gray-400\">{label}</div>\n </div>\n)\n\nconst MyLeaveWidget = () => {\n const [requests, setRequests] = useState([])\n const [ledger, setLedger] = useState([])\n const [loading, setLoading] = useState(true)\n const canSeeBalance = checkPermission(BALANCE)\n\n useEffect(() => {\n let active = true\n Promise.all([loadRows(REQUESTS), canSeeBalance ? loadRows(BALANCE) : Promise.resolve([])])\n .then(([requestRows, ledgerRows]) => {\n if (!active) return\n setRequests(requestRows)\n setLedger(ledgerRows)\n })\n .catch(() => {})\n .finally(() => active && setLoading(false))\n return () => {\n active = false\n }\n }, [canSeeBalance])\n\n const sum = (field) => ledger.reduce((total, row) => total + Number(row[field] ?? 0), 0)\n const remaining = sum('RemainingDays')\n const hasSeniority = ledger.some((row) => Number(row.YearNo) > 0) || ledger.some((row) => row.NextAccrualDate)\n const next = ledger.find((row) => row.NextAccrualDate)\n const open = requests\n .filter((row) => !row.ApprovalStatus || OPEN_STATUSES.includes(row.ApprovalStatus))\n .sort((a, b) => String(a.StartDate).localeCompare(String(b.StartDate)))\n\n return (\n <div className=\"overflow-hidden rounded-xl border border-gray-200/50 bg-white shadow-lg dark:border-gray-700/50 dark:bg-gray-800\">\n <div className=\"flex items-center gap-2 border-b border-gray-200 p-4 dark:border-gray-700\">\n <PlatformIcon name=\"FaUmbrellaBeach\" className=\"h-5 w-5 text-teal-500\" />\n <h2 className=\"text-base font-semibold text-gray-900 dark:text-white\">\n {translate('::App.DashboardWidget.MyLeave')}\n </h2>\n </div>\n <div className=\"space-y-3 p-3\">\n {loading ? (\n <div className=\"p-4 text-center text-sm text-gray-500\">...</div>\n ) : (\n <>\n {canSeeBalance && (\n <>\n <div className=\"grid grid-cols-3 gap-2\">\n <Stat\n label={translate('::App.DashboardWidget.Leave.Remaining')}\n value={formatDays(remaining)}\n className={remaining < 0 ? 'text-red-600' : 'text-teal-600 dark:text-teal-400'}\n />\n <Stat\n label={translate('::App.DashboardWidget.Leave.Used')}\n value={formatDays(sum('UsedDays'))}\n className=\"text-gray-900 dark:text-white\"\n />\n <Stat\n label={translate('::App.DashboardWidget.Leave.Pending')}\n value={formatDays(sum('PendingDays'))}\n className=\"text-orange-500\"\n />\n </div>\n {next ? (\n <div className=\"text-xs text-gray-600 dark:text-gray-300\">\n {translate('::App.DashboardWidget.Leave.NextAccrual', {\n date: formatDate(next.NextAccrualDate),\n days: formatDays(next.NextAccrualDays),\n })}\n </div>\n ) : (\n !hasSeniority && (\n <div className=\"text-xs text-gray-500 dark:text-gray-400\">\n {translate('::App.DashboardWidget.Leave.NoSeniority')}\n </div>\n )\n )}\n </>\n )}\n <div>\n <div className=\"mb-1 text-xs font-semibold text-gray-500 dark:text-gray-400\">\n {translate('::App.DashboardWidget.Leave.OpenRequests')}\n </div>\n {open.length === 0 ? (\n <div className=\"text-sm text-gray-500 dark:text-gray-400\">\n {translate('::App.DashboardWidget.Leave.NoOpenRequest')}\n </div>\n ) : (\n <ul className=\"space-y-1\">\n {open.slice(0, 3).map((row) => (\n <li\n key={row.Id}\n className=\"flex items-center justify-between gap-2 rounded-md bg-gray-50 px-2 py-1 text-xs dark:bg-gray-900/40\"\n >\n <span className=\"truncate text-gray-700 dark:text-gray-200\">\n {formatDate(row.StartDate)} – {formatDate(row.EndDate)} · {formatDays(row.Days)}{' '}\n {translate('::App.DashboardWidget.Leave.Days')}\n </span>\n <span className=\"shrink-0 rounded bg-orange-100 px-1.5 py-0.5 text-orange-700 dark:bg-orange-900/40 dark:text-orange-300\">\n {row.ApprovalStatus}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>\n </>\n )}\n <div className=\"flex flex-wrap gap-2 pt-1\">\n <a\n href={'/admin/form/' + REQUESTS}\n className=\"rounded-md bg-teal-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-teal-700\"\n >\n {translate('::App.DashboardWidget.Leave.CreateRequest')}\n </a>\n <a\n href={'/admin/list/' + REQUESTS}\n className=\"rounded-md border border-gray-300 px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700\"\n >\n {translate('::App.DashboardWidget.Leave.MyRequests')}\n </a>\n {canSeeBalance && (\n <a\n href={'/admin/list/' + BALANCE}\n className=\"rounded-md border border-gray-300 px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-200 dark:hover:bg-gray-700\"\n >\n {translate('::App.DashboardWidget.Leave.MyBalance')}\n </a>\n )}\n </div>\n </div>\n </div>\n )\n}\n\nexport default MyLeaveWidget\n",
"Props": null,
"DataSources": [],
"SeoTitle": null,
"SeoDescription": null,
"SeoKeywords": null,
"SeoOgImage": null,
"SeoCanonicalUrl": null,
"SeoNoIndex": true,
"SeoIncludeInSitemap": false,
"SeoChangeFrequency": null,
"SeoPriority": null,
"SeoStructuredData": null
}
]
}