feat: add reusable components for dialogs and headers #10
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,8 @@ export function DatePicker({
|
||||
<Calendar
|
||||
mode="single"
|
||||
selected={value ?? undefined}
|
||||
defaultMonth={value ?? undefined}
|
||||
captionLayout="dropdown"
|
||||
onSelect={onChange}
|
||||
initialFocus
|
||||
/>
|
||||
|
||||
39
resources/js/components/delete-confirm-dialog.tsx
Normal file
39
resources/js/components/delete-confirm-dialog.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import { ConfirmDialog } from '@/components/confirm-dialog';
|
||||
|
||||
type DeleteConfirmDialogProps<T> = {
|
||||
target: T | null;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
title: string;
|
||||
description?: string | ((target: T) => string);
|
||||
confirmLabel?: string;
|
||||
variant?: 'default' | 'destructive';
|
||||
onConfirm: () => void;
|
||||
};
|
||||
|
||||
export function DeleteConfirmDialog<T>({
|
||||
target,
|
||||
onOpenChange,
|
||||
title,
|
||||
description,
|
||||
confirmLabel = 'Hapus',
|
||||
variant,
|
||||
onConfirm,
|
||||
}: DeleteConfirmDialogProps<T>) {
|
||||
return (
|
||||
<ConfirmDialog
|
||||
open={target !== null}
|
||||
onOpenChange={onOpenChange}
|
||||
title={title}
|
||||
description={
|
||||
typeof description === 'function' && target
|
||||
? description(target)
|
||||
: typeof description === 'string'
|
||||
? description
|
||||
: ''
|
||||
}
|
||||
confirmLabel={confirmLabel}
|
||||
variant={variant}
|
||||
onConfirm={onConfirm}
|
||||
/>
|
||||
);
|
||||
}
|
||||
81
resources/js/components/form-dialog.tsx
Normal file
81
resources/js/components/form-dialog.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Form } from '@inertiajs/react';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type FormDialogProps = {
|
||||
open: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
title: string;
|
||||
action: React.ComponentProps<typeof Form>['action'];
|
||||
resetOnSuccess?: boolean;
|
||||
onSuccess?: () => void;
|
||||
submitDisabled?: boolean;
|
||||
submitLabel?: ReactNode;
|
||||
submittingLabel?: ReactNode;
|
||||
children:
|
||||
| ReactNode
|
||||
| ((ctx: {
|
||||
errors: Record<string, string>;
|
||||
processing: boolean;
|
||||
}) => ReactNode);
|
||||
};
|
||||
|
||||
export function FormDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
title,
|
||||
action,
|
||||
resetOnSuccess,
|
||||
onSuccess,
|
||||
submitDisabled = false,
|
||||
submitLabel = 'Simpan',
|
||||
submittingLabel = 'Menyimpan...',
|
||||
children,
|
||||
}: FormDialogProps) {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent>
|
||||
<Form
|
||||
action={action}
|
||||
resetOnSuccess={resetOnSuccess}
|
||||
onSuccess={onSuccess}
|
||||
>
|
||||
{({ errors, processing }) => (
|
||||
<>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="grid gap-4 py-4">
|
||||
{typeof children === 'function'
|
||||
? children({ errors, processing })
|
||||
: children}
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
onClick={() => onOpenChange(false)}
|
||||
>
|
||||
Batal
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={processing || submitDisabled}
|
||||
>
|
||||
{processing ? submittingLabel : submitLabel}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</>
|
||||
)}
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
21
resources/js/components/page-header.tsx
Normal file
21
resources/js/components/page-header.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
type PageHeaderProps = {
|
||||
title: string;
|
||||
description?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
};
|
||||
|
||||
export function PageHeader({ title, description, actions }: PageHeaderProps) {
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-2xl font-semibold tracking-tight">
|
||||
{title}
|
||||
</h2>
|
||||
{description}
|
||||
</div>
|
||||
{actions}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
67
resources/js/components/row-actions.tsx
Normal file
67
resources/js/components/row-actions.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
import { Link } from '@inertiajs/react';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export type RowAction = {
|
||||
label: string;
|
||||
icon: ReactNode;
|
||||
iconClassName?: string;
|
||||
show?: boolean;
|
||||
onClick?: () => void;
|
||||
href?: string;
|
||||
};
|
||||
|
||||
type RowActionsProps = {
|
||||
actions: RowAction[];
|
||||
wrapperClassName?: string;
|
||||
};
|
||||
|
||||
export function RowActions({
|
||||
actions,
|
||||
wrapperClassName = 'flex items-center justify-center gap-1',
|
||||
}: RowActionsProps) {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<div className={wrapperClassName}>
|
||||
{actions
|
||||
.filter((action) => action.show !== false)
|
||||
.map((action) => (
|
||||
<Tooltip key={action.label}>
|
||||
<TooltipTrigger asChild>
|
||||
{action.href ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
asChild
|
||||
className={action.iconClassName}
|
||||
>
|
||||
<Link href={action.href}>
|
||||
{action.icon}
|
||||
</Link>
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={action.onClick}
|
||||
className={action.iconClassName}
|
||||
>
|
||||
{action.icon}
|
||||
</Button>
|
||||
)}
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">
|
||||
{action.label}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
);
|
||||
}
|
||||
118
resources/js/hooks/use-server-table.tsx
Normal file
118
resources/js/hooks/use-server-table.tsx
Normal file
@ -0,0 +1,118 @@
|
||||
import type { PaginationState } from '@/components/data-table';
|
||||
import { router } from '@inertiajs/react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
type UseServerTableOptions = {
|
||||
route: () => string;
|
||||
pagination: PaginationState;
|
||||
filters?: Record<string, string | undefined>;
|
||||
filterWithParams?: boolean;
|
||||
};
|
||||
|
||||
export function useServerTable({
|
||||
route,
|
||||
pagination,
|
||||
filters,
|
||||
filterWithParams = true,
|
||||
}: UseServerTableOptions) {
|
||||
const [search, setSearch] = useState('');
|
||||
const [filterOpen, setFilterOpen] = useState(false);
|
||||
|
||||
const handlePageChange = useCallback(
|
||||
(page: number) => {
|
||||
router.get(
|
||||
route(),
|
||||
{
|
||||
...filters,
|
||||
page,
|
||||
per_page: pagination.per_page,
|
||||
search,
|
||||
},
|
||||
{ preserveState: true, replace: true },
|
||||
);
|
||||
},
|
||||
[route, filters, pagination.per_page, search],
|
||||
);
|
||||
|
||||
const handlePerPageChange = useCallback(
|
||||
(perPage: number) => {
|
||||
router.get(
|
||||
route(),
|
||||
{
|
||||
...filters,
|
||||
page: 1,
|
||||
per_page: perPage,
|
||||
search,
|
||||
},
|
||||
{ preserveState: true, replace: true },
|
||||
);
|
||||
},
|
||||
[route, filters, search],
|
||||
);
|
||||
|
||||
const handleSearchChange = useCallback(
|
||||
(value: string) => {
|
||||
setSearch(value);
|
||||
router.get(
|
||||
route(),
|
||||
{
|
||||
...filters,
|
||||
page: 1,
|
||||
per_page: pagination.per_page,
|
||||
search: value,
|
||||
},
|
||||
{ preserveState: true, replace: true },
|
||||
);
|
||||
},
|
||||
[route, filters, pagination.per_page],
|
||||
);
|
||||
|
||||
function applyFilter(key: string, value: string) {
|
||||
const newFilters = { ...filters };
|
||||
|
||||
if (value === '' || value === 'all') {
|
||||
delete newFilters[key];
|
||||
} else {
|
||||
newFilters[key] = value;
|
||||
}
|
||||
|
||||
router.get(
|
||||
route(),
|
||||
filterWithParams
|
||||
? {
|
||||
...newFilters,
|
||||
page: 1,
|
||||
per_page: pagination.per_page,
|
||||
search,
|
||||
}
|
||||
: newFilters,
|
||||
{ preserveState: true, replace: true },
|
||||
);
|
||||
}
|
||||
|
||||
function clearFilters() {
|
||||
router.get(
|
||||
route(),
|
||||
filterWithParams
|
||||
? {
|
||||
page: 1,
|
||||
per_page: pagination.per_page,
|
||||
search,
|
||||
}
|
||||
: {},
|
||||
{ preserveState: true, replace: true },
|
||||
);
|
||||
setFilterOpen(false);
|
||||
}
|
||||
|
||||
return {
|
||||
search,
|
||||
filterOpen,
|
||||
setFilterOpen,
|
||||
handlePageChange,
|
||||
handlePerPageChange,
|
||||
handleSearchChange,
|
||||
applyFilter,
|
||||
clearFilters,
|
||||
};
|
||||
}
|
||||
@ -1,614 +0,0 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"header": "Cover page",
|
||||
"type": "Cover page",
|
||||
"status": "In Process",
|
||||
"target": "18",
|
||||
"limit": "5",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"header": "Table of contents",
|
||||
"type": "Table of contents",
|
||||
"status": "Done",
|
||||
"target": "29",
|
||||
"limit": "24",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"header": "Executive summary",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "10",
|
||||
"limit": "13",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"header": "Technical approach",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "27",
|
||||
"limit": "23",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"header": "Design",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "2",
|
||||
"limit": "16",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"header": "Capabilities",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "20",
|
||||
"limit": "8",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"header": "Integration with existing systems",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "21",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"header": "Innovation and Advantages",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "25",
|
||||
"limit": "26",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"header": "Overview of EMR's Innovative Solutions",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "7",
|
||||
"limit": "23",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"header": "Advanced Algorithms and Machine Learning",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "28",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"header": "Adaptive Communication Protocols",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "9",
|
||||
"limit": "31",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"header": "Advantages Over Current Technologies",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "12",
|
||||
"limit": "0",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"header": "Past Performance",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "33",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"header": "Customer Feedback and Satisfaction Levels",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "15",
|
||||
"limit": "34",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"header": "Implementation Challenges and Solutions",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "3",
|
||||
"limit": "35",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"header": "Security Measures and Data Protection Policies",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "6",
|
||||
"limit": "36",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"header": "Scalability and Future Proofing",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "4",
|
||||
"limit": "37",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"header": "Cost-Benefit Analysis",
|
||||
"type": "Plain language",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "38",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"header": "User Training and Onboarding Experience",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "17",
|
||||
"limit": "39",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"header": "Future Development Roadmap",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "11",
|
||||
"limit": "40",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"header": "System Architecture Overview",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "24",
|
||||
"limit": "18",
|
||||
"reviewer": "Maya Johnson"
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"header": "Risk Management Plan",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "15",
|
||||
"limit": "22",
|
||||
"reviewer": "Carlos Rodriguez"
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"header": "Compliance Documentation",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "31",
|
||||
"limit": "27",
|
||||
"reviewer": "Sarah Chen"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"header": "API Documentation",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "8",
|
||||
"limit": "12",
|
||||
"reviewer": "Raj Patel"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"header": "User Interface Mockups",
|
||||
"type": "Visual",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "25",
|
||||
"reviewer": "Leila Ahmadi"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"header": "Database Schema",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "20",
|
||||
"reviewer": "Thomas Wilson"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"header": "Testing Methodology",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "17",
|
||||
"limit": "14",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"header": "Deployment Strategy",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "30",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"header": "Budget Breakdown",
|
||||
"type": "Financial",
|
||||
"status": "In Process",
|
||||
"target": "13",
|
||||
"limit": "16",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"header": "Market Analysis",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "29",
|
||||
"limit": "32",
|
||||
"reviewer": "Sophia Martinez"
|
||||
},
|
||||
{
|
||||
"id": 31,
|
||||
"header": "Competitor Comparison",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "19",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 32,
|
||||
"header": "Maintenance Plan",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "16",
|
||||
"limit": "23",
|
||||
"reviewer": "Alex Thompson"
|
||||
},
|
||||
{
|
||||
"id": 33,
|
||||
"header": "User Personas",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "24",
|
||||
"reviewer": "Nina Patel"
|
||||
},
|
||||
{
|
||||
"id": 34,
|
||||
"header": "Accessibility Compliance",
|
||||
"type": "Legal",
|
||||
"status": "Done",
|
||||
"target": "18",
|
||||
"limit": "21",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 35,
|
||||
"header": "Performance Metrics",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "23",
|
||||
"limit": "26",
|
||||
"reviewer": "David Kim"
|
||||
},
|
||||
{
|
||||
"id": 36,
|
||||
"header": "Disaster Recovery Plan",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "17",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 37,
|
||||
"header": "Third-party Integrations",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "25",
|
||||
"limit": "28",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 38,
|
||||
"header": "User Feedback Summary",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "20",
|
||||
"limit": "15",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 39,
|
||||
"header": "Localization Strategy",
|
||||
"type": "Narrative",
|
||||
"status": "In Process",
|
||||
"target": "12",
|
||||
"limit": "19",
|
||||
"reviewer": "Maria Garcia"
|
||||
},
|
||||
{
|
||||
"id": 40,
|
||||
"header": "Mobile Compatibility",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "28",
|
||||
"limit": "31",
|
||||
"reviewer": "James Wilson"
|
||||
},
|
||||
{
|
||||
"id": 41,
|
||||
"header": "Data Migration Plan",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "22",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 42,
|
||||
"header": "Quality Assurance Protocols",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "33",
|
||||
"reviewer": "Priya Singh"
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"header": "Stakeholder Analysis",
|
||||
"type": "Research",
|
||||
"status": "In Process",
|
||||
"target": "11",
|
||||
"limit": "14",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"header": "Environmental Impact Assessment",
|
||||
"type": "Research",
|
||||
"status": "Done",
|
||||
"target": "24",
|
||||
"limit": "27",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 45,
|
||||
"header": "Intellectual Property Rights",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "17",
|
||||
"limit": "20",
|
||||
"reviewer": "Sarah Johnson"
|
||||
},
|
||||
{
|
||||
"id": 46,
|
||||
"header": "Customer Support Framework",
|
||||
"type": "Narrative",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "25",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 47,
|
||||
"header": "Version Control Strategy",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "15",
|
||||
"limit": "18",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 48,
|
||||
"header": "Continuous Integration Pipeline",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "29",
|
||||
"reviewer": "Michael Chen"
|
||||
},
|
||||
{
|
||||
"id": 49,
|
||||
"header": "Regulatory Compliance",
|
||||
"type": "Legal",
|
||||
"status": "In Process",
|
||||
"target": "13",
|
||||
"limit": "16",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 50,
|
||||
"header": "User Authentication System",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "28",
|
||||
"limit": "31",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 51,
|
||||
"header": "Data Analytics Framework",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "24",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 52,
|
||||
"header": "Cloud Infrastructure",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "16",
|
||||
"limit": "19",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 53,
|
||||
"header": "Network Security Measures",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "29",
|
||||
"limit": "32",
|
||||
"reviewer": "Lisa Wong"
|
||||
},
|
||||
{
|
||||
"id": 54,
|
||||
"header": "Project Timeline",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "14",
|
||||
"limit": "17",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 55,
|
||||
"header": "Resource Allocation",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "30",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 56,
|
||||
"header": "Team Structure and Roles",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "20",
|
||||
"limit": "23",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 57,
|
||||
"header": "Communication Protocols",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "15",
|
||||
"limit": "18",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 58,
|
||||
"header": "Success Metrics",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "30",
|
||||
"limit": "33",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 59,
|
||||
"header": "Internationalization Support",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "23",
|
||||
"limit": "26",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 60,
|
||||
"header": "Backup and Recovery Procedures",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "18",
|
||||
"limit": "21",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 61,
|
||||
"header": "Monitoring and Alerting System",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "25",
|
||||
"limit": "28",
|
||||
"reviewer": "Daniel Park"
|
||||
},
|
||||
{
|
||||
"id": 62,
|
||||
"header": "Code Review Guidelines",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "12",
|
||||
"limit": "15",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 63,
|
||||
"header": "Documentation Standards",
|
||||
"type": "Technical content",
|
||||
"status": "In Process",
|
||||
"target": "27",
|
||||
"limit": "30",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 64,
|
||||
"header": "Release Management Process",
|
||||
"type": "Planning",
|
||||
"status": "Done",
|
||||
"target": "22",
|
||||
"limit": "25",
|
||||
"reviewer": "Assign reviewer"
|
||||
},
|
||||
{
|
||||
"id": 65,
|
||||
"header": "Feature Prioritization Matrix",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "19",
|
||||
"limit": "22",
|
||||
"reviewer": "Emma Davis"
|
||||
},
|
||||
{
|
||||
"id": 66,
|
||||
"header": "Technical Debt Assessment",
|
||||
"type": "Technical content",
|
||||
"status": "Done",
|
||||
"target": "24",
|
||||
"limit": "27",
|
||||
"reviewer": "Eddie Lake"
|
||||
},
|
||||
{
|
||||
"id": 67,
|
||||
"header": "Capacity Planning",
|
||||
"type": "Planning",
|
||||
"status": "In Process",
|
||||
"target": "21",
|
||||
"limit": "24",
|
||||
"reviewer": "Jamik Tashpulatov"
|
||||
},
|
||||
{
|
||||
"id": 68,
|
||||
"header": "Service Level Agreements",
|
||||
"type": "Legal",
|
||||
"status": "Done",
|
||||
"target": "26",
|
||||
"limit": "29",
|
||||
"reviewer": "Assign reviewer"
|
||||
}
|
||||
]
|
||||
Loading…
Reference in New Issue
Block a user