30 lines
7.9 KiB
JSON
30 lines
7.9 KiB
JSON
|
|
{
|
|||
|
|
"ListFormCode": "Sas.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 = 'Hr.MyLeaveRequest'\nconst BALANCE = '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('::Sas.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('::Sas.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('::Sas.DashboardWidget.Leave.Used')}\n value={formatDays(sum('UsedDays'))}\n className=\"text-gray-900 dark:text-white\"\n />\n <Stat\n label={translate('::Sas.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-30
|
|||
|
|
"Props": null,
|
|||
|
|
"DataSources": [],
|
|||
|
|
"SeoTitle": null,
|
|||
|
|
"SeoDescription": null,
|
|||
|
|
"SeoKeywords": null,
|
|||
|
|
"SeoOgImage": null,
|
|||
|
|
"SeoCanonicalUrl": null,
|
|||
|
|
"SeoNoIndex": true,
|
|||
|
|
"SeoIncludeInSitemap": false,
|
|||
|
|
"SeoChangeFrequency": null,
|
|||
|
|
"SeoPriority": null,
|
|||
|
|
"SeoStructuredData": null
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
}
|