Skip to content

Commit 8fba597

Browse files
authored
JSONビューアーの追加と永続処理の追加 (#39)
2 parents 0cf965b + aac16d8 commit 8fba597

9 files changed

Lines changed: 311 additions & 8 deletions

File tree

.replit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
modules = ["nodejs-20"]
1+
modules = ["nodejs-20", "nodejs-21"]
22
run = "yarn run dev"
33

44
[nix]

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"react": "^18.3.1",
3535
"react-dom": "^18.3.1",
3636
"react-hook-form": "^7.53.0",
37+
"react-json-view": "^1.21.3",
3738
"rsuite": "^5.70.0",
3839
"timezones-list": "^3.0.3",
3940
"uuid": "^10.0.0"

src/app/image_generator/useImageGenerator.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Color } from 'antd/es/color-picker';
2-
import { ColorFactory } from 'antd/es/color-picker/color';
2+
import { AggregationColor } from 'antd/es/color-picker/color';
33
import { useCallback, useState } from 'react';
44
import { getPresetSize } from '@/app/image_generator/presetSize';
55
import { useCustomForm } from '@/components/common/Form/useCustomForm';
@@ -19,8 +19,8 @@ export const DEFAULT_VALUES: ImageGeneratorForm = {
1919
wight: 256,
2020
height: 256,
2121
type: 'jpg',
22-
bgColor: new ColorFactory('ffffff00'),
23-
textColor: new ColorFactory('1668dc00'),
22+
bgColor: new AggregationColor('ffffff'),
23+
textColor: new AggregationColor('1668dc'),
2424
tab: 'unsplash',
2525
text: '',
2626
textSize: undefined,
@@ -67,7 +67,6 @@ export const useImageGenerator = () => {
6767

6868
const onClickGenerate = useCallback(() => {
6969
const values = getValues();
70-
console.log(values);
7170
switch (values.tab) {
7271
case 'unsplash':
7372
setSrc(createUnsplashURL(values));

src/app/json_view/JsonView.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use client';
2+
import React, { FC } from 'react';
3+
import dynamic from 'next/dynamic';
4+
import { Controller, FormProvider } from 'react-hook-form';
5+
import { Col, Grid, Panel, PanelGroup, Row } from 'rsuite';
6+
import { AppLayout } from '@/Layout/App';
7+
import { useJsonView } from '@/app/json_view/useJsonView';
8+
import { Editor, ex } from '@/components/common/Editor';
9+
import { ClearButton } from '@/components/common/Form/ClearButton';
10+
import { CopyButton } from '@/components/common/Form/CopyButton';
11+
import { PageTitle } from '@/components/common/PageTitle';
12+
import { PanelHeader } from '@/components/common/PanelHeader';
13+
const ReactJson = dynamic(() => import('react-json-view'), {
14+
ssr: false,
15+
});
16+
17+
export const JsonView: FC = () => {
18+
const title = 'JSONビューアー';
19+
const { input, methods } = useJsonView();
20+
21+
return (
22+
<FormProvider {...methods}>
23+
<AppLayout>
24+
<Grid fluid>
25+
<PageTitle title={title} />
26+
<Row gutter={5}>
27+
<Col xs={24} md={12}>
28+
<PanelGroup bordered>
29+
<Panel
30+
bordered
31+
header={<PanelHeader title="入力" right={<ClearButton name="input" />} />}
32+
>
33+
<Controller
34+
render={({ field }) => <Editor extensions={[ex.json]} {...field} />}
35+
name="input"
36+
control={methods.control}
37+
/>
38+
</Panel>
39+
</PanelGroup>
40+
</Col>
41+
<Col xs={24} md={12}>
42+
<Panel
43+
bordered
44+
header={
45+
<PanelHeader
46+
title="JSON"
47+
right={<CopyButton size="small" copyText={JSON.stringify(input)} />}
48+
/>
49+
}
50+
>
51+
<ReactJson
52+
src={input}
53+
theme="chalk"
54+
style={{ padding: '4px', border: '1px solid #a4a9b3', borderRadius: '6px' }}
55+
/>
56+
</Panel>
57+
</Col>
58+
</Row>
59+
</Grid>
60+
</AppLayout>
61+
</FormProvider>
62+
);
63+
};

src/app/json_view/page.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import React, { FC } from 'react';
2+
import { JsonView } from './JsonView';
3+
4+
export const metadata = {
5+
title: 'Dev Toolkit - JSONビューアー',
6+
};
7+
8+
const JsonViewPage: FC = () => {
9+
return <JsonView />;
10+
};
11+
12+
export default JsonViewPage;

src/app/json_view/useJsonView.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { useCustomForm } from '@/components/common/Form/useCustomForm';
2+
import { useFormPersistence } from '@/hooks/useFormPersistence';
3+
4+
type JsonFormatForm = {
5+
input: string;
6+
};
7+
8+
const DEFAULT_VALUES: JsonFormatForm = {
9+
input: '',
10+
};
11+
12+
export const useJsonView = () => {
13+
const methods = useCustomForm<JsonFormatForm>({
14+
defaultValues: DEFAULT_VALUES,
15+
});
16+
const { watch, setValue } = methods;
17+
useFormPersistence('json_view', methods, (defaultValues) => {
18+
setValue('input', defaultValues?.input);
19+
});
20+
21+
const input = toJson(watch('input', DEFAULT_VALUES.input));
22+
23+
return {
24+
DEFAULT_VALUES,
25+
methods,
26+
input,
27+
};
28+
};
29+
30+
const toJson = (input: string): object => {
31+
try {
32+
return JSON.parse(input);
33+
} catch {
34+
return {};
35+
}
36+
};

src/components/common/Features.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ export const features: FeatureGroupType[] = [
7474
title: 'JSONフォーマット',
7575
path: '/json_formatter',
7676
},
77+
{
78+
key: 'json_view',
79+
title: 'JSONビューアー',
80+
path: '/json_view',
81+
},
7782
],
7883
},
7984
{

src/hooks/useFormPersistence.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useEffect } from 'react';
2+
import type { UseFormReturn } from 'react-hook-form';
3+
4+
// フォームの情報をlocalStorageに保存して永続化する
5+
export const useFormPersistence = <T>(
6+
name: string,
7+
methods: UseFormReturn<T>,
8+
setCallback: (defaultValues: T) => void,
9+
) => {
10+
const {
11+
watch,
12+
formState: { isDirty },
13+
} = methods;
14+
const formData = watch();
15+
16+
useEffect(() => {
17+
const defaultValues = JSON.parse(localStorage.getItem(name));
18+
if (!isDirty) {
19+
setCallback(defaultValues);
20+
}
21+
}, [isDirty]);
22+
23+
useEffect(() => {
24+
if (isDirty) {
25+
localStorage.setItem(name, JSON.stringify(formData));
26+
console.log('set', isDirty, formData);
27+
}
28+
}, [formData, isDirty]);
29+
};

0 commit comments

Comments
 (0)