+ {hasInteracted && isValid === false && (
+
+ )}
+
+ {hasInteracted && isValid === false
+ ? React.cloneElement(children as React.ReactElement, { value: '' })
+ : children}
+
+
+);
+
+export default ValidatedToolResult;
diff --git a/src/pages/tools/time/crontab-guru/crontab-guru.service.test.ts b/src/pages/tools/time/crontab-guru/crontab-guru.service.test.ts
new file mode 100644
index 0000000..bce7fd9
--- /dev/null
+++ b/src/pages/tools/time/crontab-guru/crontab-guru.service.test.ts
@@ -0,0 +1,26 @@
+import { expect, describe, it } from 'vitest';
+import { validateCrontab, explainCrontab } from './service';
+
+describe('crontab-guru service', () => {
+ it('validates correct crontab expressions', () => {
+ expect(validateCrontab('35 16 * * 0-5')).toBe(true);
+ expect(validateCrontab('* * * * *')).toBe(true);
+ expect(validateCrontab('0 12 1 * *')).toBe(true);
+ });
+
+ it('invalidates incorrect crontab expressions', () => {
+ expect(validateCrontab('invalid expression')).toBe(false);
+ expect(validateCrontab('61 24 * * *')).toBe(false);
+ });
+
+ it('explains valid crontab expressions', () => {
+ expect(explainCrontab('35 16 * * 0-5')).toMatch(/At 04:35 PM/);
+ expect(explainCrontab('* * * * *')).toMatch(/Every minute/);
+ });
+
+ it('returns error for invalid crontab explanation', () => {
+ expect(explainCrontab('invalid expression')).toMatch(
+ /Invalid crontab expression/
+ );
+ });
+});
diff --git a/src/pages/tools/time/crontab-guru/index.tsx b/src/pages/tools/time/crontab-guru/index.tsx
new file mode 100644
index 0000000..11246e7
--- /dev/null
+++ b/src/pages/tools/time/crontab-guru/index.tsx
@@ -0,0 +1,128 @@
+import { Alert } from '@mui/material';
+import React, { useState } from 'react';
+import ToolContent from '@components/ToolContent';
+import { ToolComponentProps } from '@tools/defineTool';
+import ToolTextInput from '@components/input/ToolTextInput';
+import ToolTextResult from '@components/result/ToolTextResult';
+import { CardExampleType } from '@components/examples/ToolExamples';
+import { main, validateCrontab } from './service';
+
+const initialValues = {};
+
+type InitialValuesType = typeof initialValues;
+
+const exampleCards: CardExampleType