Skip to content

Commit

Permalink
Merge pull request #9 from Gimnath-Perera/feat/inter-mock-connection
Browse files Browse the repository at this point in the history
feat: extract & clean interfaces
  • Loading branch information
gimnathperera committed Sep 10, 2023
2 parents aaea1c6 + b298a96 commit aacf014
Show file tree
Hide file tree
Showing 10 changed files with 1,095 additions and 323 deletions.
36 changes: 21 additions & 15 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
'use client';
import { FC, useState } from 'react';
import { FC, useRef, useState } from 'react';
import { useDisclosure } from '@nextui-org/react';
import CodeEditor from '@/components/code-editor';
import Header from '@/components/header';
import Result from '@/components/result';

const DEFAULT_INTERFACE = `// You can use typescript interfaces like following;
interface Person {
id: number;
firstName: string;
lastName: string;
age: number;
bio: string;
}
`;
import { extractInterfaceNames } from '@/utils';
import { Initials } from '@/config/constants';
import InterfaceSelectModal from '@/components/interface-select-modal';

const Home: FC = () => {
const [code, setCode] = useState<string>(DEFAULT_INTERFACE);
const [numberOfRows, setNumberOfRows] = useState(new Set(['10']));
const { isOpen, onOpen, onOpenChange } = useDisclosure();
const [code, setCode] = useState<string>(Initials.DefaultInterface);
const [numberOfRows, setNumberOfRows] = useState(new Set(['1']));

const selectedInterfaces = useRef<string[] | null>(null);

const handleOnGenerate = (): void => {
console.log('*********', code);
const interfaceNamesToMock = extractInterfaceNames(code);
selectedInterfaces.current = interfaceNamesToMock;
onOpen();
};

// TODO: fix any type here
const handleOnRowCountChange = (newRowCount: any): void => {
setNumberOfRows(newRowCount);
};

const handleOnCodeChange = (newCode: string): void => {
setCode(newCode);
};
Expand All @@ -41,6 +41,12 @@ const Home: FC = () => {
<CodeEditor onCodeChange={handleOnCodeChange} initialCode={code} />
<Result />
</div>

<InterfaceSelectModal
isOpen={isOpen}
onOpenChange={onOpenChange}
selectedInterfaces={selectedInterfaces.current}
/>
</section>
);
};
Expand Down
8 changes: 4 additions & 4 deletions components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,26 @@ const Header: FC<Props> = ({ onGenerate, onRowCountChange, numberOfRows }) => {
return (
<div className='pb-6 text-center flex items-center justify-between'>
<h1 className='tracking-tight inline font-semibold text-[2.3rem] lg:text-3xl'>
Generate Fake Data
Generate 𝔽𝕒𝕜𝕖 Data
</h1>
<div className='flex items-center gap-4'>
<Dropdown>
<DropdownTrigger>
<Button variant='bordered' className='capitalize'>
{`#️⃣ Scale [${selectedValue} of rows]`}
{`#️⃣ Scale [${selectedValue} of row${Number(selectedValue) > 1 ? 's' : ''}]`}
</Button>
</DropdownTrigger>
<DropdownMenu
aria-label='Single selection example'
aria-label='row-count-select'
variant='flat'
disallowEmptySelection
selectionMode='single'
selectedKeys={numberOfRows}
onSelectionChange={onRowCountChange}
>
<DropdownItem key='1'>1</DropdownItem>
<DropdownItem key='10'>10</DropdownItem>
<DropdownItem key='50'>50</DropdownItem>
<DropdownItem key='100'>100</DropdownItem>
</DropdownMenu>
</Dropdown>

Expand Down
61 changes: 61 additions & 0 deletions components/interface-select-content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { FC, useState } from 'react';
import { Listbox, ListboxItem } from '@nextui-org/react';
import { Chip } from '@nextui-org/react';

const InterfaceSelectContent: FC = () => {
const [selectedKeys, setSelectedKeys] = useState<Set<string> | any>(new Set(['text']));

const backgroundColors: string[] = [
'bg-primary',
'bg-secondary',
'bg-warning',
'bg-danger',
'bg-default',
];
const handleChipClose = (closedInterface: string): void => {
if (selectedKeys.size === 1) return;
const newSelectedKeys = new Set(
Array.from(selectedKeys).filter(key => key !== closedInterface),
);
setSelectedKeys(newSelectedKeys);
};

return (
<div className='flex flex-col gap-2'>
<Listbox
aria-label='Multiple selection example'
variant='flat'
disallowEmptySelection
selectionMode='multiple'
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
<ListboxItem key='text'>⚡ Text</ListboxItem>
<ListboxItem key='number'>⚡ Number</ListboxItem>
<ListboxItem key='date'>⚡ Date</ListboxItem>
<ListboxItem key='single_date'>⚡ Single Date</ListboxItem>
<ListboxItem key='iteration'>⚡ Iteration</ListboxItem>
</Listbox>
<div className='flex flex-wrap gap-2 items-center'>
<p className='text-small text-default-500'>Selected interfaces: </p>
{Array.from(selectedKeys).map((selectedInterface: any, index: number) => (
<Chip
size='sm'
radius='full'
variant='flat'
key={selectedInterface}
onClose={(): void => handleChipClose(selectedInterface)}
classNames={{
base: backgroundColors[index % backgroundColors.length],
content: 'text-white',
}}
>
{selectedInterface}
</Chip>
))}
</div>
</div>
);
};

export default InterfaceSelectContent;
50 changes: 50 additions & 0 deletions components/interface-select-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { FC } from 'react';
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
Button,
} from '@nextui-org/react';
import InterfaceSelectContent from '@/components/interface-select-content';

interface Props {
isOpen: boolean;
selectedInterfaces: string[] | null;
onOpenChange: () => void;
}

const InterfaceSelectModal: FC<Props> = ({ isOpen, onOpenChange, selectedInterfaces }) => {
console.log('🚀 ~ file: index.tsx:18 ~ selectedInterfaces:', selectedInterfaces);

return (
<>
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent>
{(onClose): any => (
<>
<ModalHeader className='flex flex-col gap-1'>
Following 𝕀𝕟𝕥𝕖𝕣𝕗𝕒𝕔𝕖𝕤 Detected
</ModalHeader>
<ModalBody>
<p>Please select the interfaces you want to generate mock data for.</p>
<InterfaceSelectContent />
</ModalBody>
<ModalFooter>
<Button color='danger' variant='bordered' onPress={onClose}>
Close
</Button>
<Button color='primary' onPress={onClose}>
🪄 Generate
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
);
};

export default InterfaceSelectModal;
35 changes: 35 additions & 0 deletions config/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
export const Initials = {
DefaultInterface: `// You can use typescript interfaces like following;
interface Admin extends User {
adminRecord: AdminRecord;
}
interface Student extends User {
schoolRecord: SchoolRecord;
}
interface User {
firstName: string;
lastName: string;
username: string;
emailAddress: string;
}
interface AdminRecord {
studentsPassedEachYear: number[];
}
interface SchoolRecord {
startDate: string;
endDate: string;
isActive: boolean;
grades: number[];
}
`,
};

export const RegexExp = {
InterfaceName: /interface\s+(\w+)/g,
Interface: /interface\s+(\w+)\s*{[^}]*}/gs,
};
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@nextui-org/kbd": "2.0.8",
"@nextui-org/link": "2.0.9",
"@nextui-org/navbar": "2.0.9",
"@nextui-org/react": "^2.0.24",
"@nextui-org/react": "^2.1.10",
"@nextui-org/snippet": "2.0.10",
"@nextui-org/switch": "2.0.9",
"@nextui-org/system": "2.0.5",
Expand All @@ -37,6 +37,7 @@
"eslint": "^8.47.0",
"eslint-config-next": "13.4.4",
"framer-motion": "^10.15.1",
"intermock": "^0.2.5",
"intl-messageformat": "^10.1.0",
"next": "13.4.13",
"next-themes": "^0.2.1",
Expand Down
7 changes: 7 additions & 0 deletions utils/extract-interface-names/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RegexExp } from '@/config/constants';

export const extractInterfaceNames = (code: string): string[] => {
const matches = code.match(RegexExp.InterfaceName);

return matches ? matches.map(match => match.split(' ')[1]) : [];
};
15 changes: 15 additions & 0 deletions utils/generate-mocks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { mock } from 'intermock';

export const generateMocks = (
code: string,
selectedInterfaces: string[],
): string | Record<string | number, {}> => {
const mockedData = mock({
language: 'typescript',
files: [['docs', code]],
output: 'string',
interfaces: selectedInterfaces,
});

return mockedData;
};
2 changes: 2 additions & 0 deletions utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './extract-interface-names';
export * from './generate-mocks';
Loading

0 comments on commit aacf014

Please sign in to comment.