Skip to content

Commit 54c6f84

Browse files
author
Erick Moreira
committed
refactor: Melhorias na tipagem e correções de linter
1 parent 8afdac8 commit 54c6f84

File tree

8 files changed

+388
-128
lines changed

8 files changed

+388
-128
lines changed

.eslintrc.json

+19-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
{
2-
"extends": ["next/core-web-vitals", "next/typescript", "standard", "plugin:tailwindcss/recommended", "prettier" ],
2+
"extends": [
3+
"next/core-web-vitals",
4+
"plugin:@typescript-eslint/recommended",
5+
"plugin:@typescript-eslint/recommended-requiring-type-checking"
6+
],
7+
"parser": "@typescript-eslint/parser",
8+
"plugins": ["@typescript-eslint"],
39
"rules": {
4-
"no-undef": "off"
10+
"@typescript-eslint/explicit-function-return-type": "warn",
11+
"@typescript-eslint/no-unused-vars": "error",
12+
"@typescript-eslint/no-explicit-any": "error",
13+
"@typescript-eslint/no-unsafe-assignment": "warn",
14+
"@typescript-eslint/no-unsafe-member-access": "warn",
15+
"@typescript-eslint/no-unsafe-call": "warn",
16+
"@typescript-eslint/no-unsafe-return": "warn",
17+
"@typescript-eslint/restrict-template-expressions": "warn",
18+
"@typescript-eslint/unbound-method": "warn"
19+
},
20+
"parserOptions": {
21+
"project": "./tsconfig.json"
522
}
623
}

.husky/pre-commit

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
3+
4+
npm run type-check
5+
npx lint-staged

.prettierrc

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"semi": true,
3+
"trailingComma": "es5",
4+
"singleQuote": true,
5+
"printWidth": 100,
6+
"tabWidth": 2,
7+
"useTabs": false,
8+
"arrowParens": "avoid",
9+
"bracketSpacing": true,
10+
"endOfLine": "lf",
11+
"parser": "typescript"
12+
}

components/ActionDropdown.tsx

+12-9
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ import { renameFile, updateFileUsers, deleteFile } from "@/lib/actions/file.acti
1818
import { useToast } from "@/components/ui/use-toast";
1919
import { constructDownloadUrl } from "@/lib/utils";
2020
import { usePathname } from "next/navigation";
21-
22-
type ActionType = "rename" | "share" | "delete" | "details" | "download";
21+
import { FileActionType } from "@/types/file";
2322

2423
const ActionDropdown = ({ file }: { file: Models.Document }) => {
2524
const [isModalOpen, setIsModalOpen] = useState(false);
26-
const [action, setAction] = useState<ActionType | null>(null);
25+
const [action, setAction] = useState<FileActionType | null>(null);
2726
const [newName, setNewName] = useState(file.name);
28-
const [emails, setEmails] = useState<string[]>(file.users || []);
27+
const [emails, setEmails] = useState<string[]>(file.users as string[] || []);
2928
const [isLoading, setIsLoading] = useState(false);
3029
const { toast } = useToast();
3130
const path = usePathname() || "/";
@@ -34,10 +33,10 @@ const ActionDropdown = ({ file }: { file: Models.Document }) => {
3433
setIsModalOpen(false);
3534
setAction(null);
3635
setNewName(file.name);
37-
setEmails(file.users || []);
36+
setEmails(file.users as string[] || []);
3837
};
3938

40-
const handleAction = async (value: ActionType) => {
39+
const handleAction = async (value: FileActionType) => {
4140
if (value === "download") {
4241
window.open(constructDownloadUrl(file.bucketFileId), "_blank");
4342
return;
@@ -107,6 +106,10 @@ const ActionDropdown = ({ file }: { file: Models.Document }) => {
107106
}
108107
};
109108

109+
const handleClick = (value: FileActionType) => {
110+
handleAction(value).catch(console.error);
111+
};
112+
110113
const renderDialogContent = () => {
111114
if (!isModalOpen) return null;
112115

@@ -134,7 +137,7 @@ const ActionDropdown = ({ file }: { file: Models.Document }) => {
134137
<Button variant="outline" onClick={closeAllModals}>
135138
Cancelar
136139
</Button>
137-
<Button onClick={() => handleAction("rename")} disabled={isLoading}>
140+
<Button onClick={() => handleClick("rename")} disabled={isLoading}>
138141
{isLoading ? "Renomeando..." : "Renomear"}
139142
</Button>
140143
</div>
@@ -150,7 +153,7 @@ const ActionDropdown = ({ file }: { file: Models.Document }) => {
150153
</Button>
151154
<Button
152155
variant="destructive"
153-
onClick={() => handleAction("delete")}
156+
onClick={() => handleClick("delete")}
154157
disabled={isLoading}
155158
>
156159
{isLoading ? "Excluindo..." : "Excluir"}
@@ -181,7 +184,7 @@ const ActionDropdown = ({ file }: { file: Models.Document }) => {
181184
{actionsDropdownItems.map(({ label, icon, value }) => (
182185
<DropdownMenuItem
183186
key={value}
184-
onClick={() => handleAction(value as ActionType)}
187+
onClick={() => handleClick(value as FileActionType)}
185188
className="flex cursor-pointer items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700"
186189
>
187190
<Image src={icon} alt={label} width={16} height={16} />

components/FileUploader.tsx

+117-116
Original file line numberDiff line numberDiff line change
@@ -24,144 +24,145 @@ const FileUploader = ({ ownerId, accountId, className }: Props) => {
2424
const [files, setFiles] = useState<File[]>([]);
2525
const [uploadingFiles, setUploadingFiles] = useState<Set<string>>(new Set());
2626

27-
const onDrop = useCallback(
28-
async (acceptedFiles: File[]) => {
29-
console.log('Files dropped:', acceptedFiles.map(f => ({
30-
name: f.name,
31-
size: f.size,
32-
type: f.type,
33-
lastModified: f.lastModified
34-
})));
35-
36-
for (const file of acceptedFiles) {
37-
if (file.size > MAX_FILE_SIZE) {
38-
console.log('File too large:', {
39-
name: file.name,
40-
size: file.size,
41-
maxSize: MAX_FILE_SIZE
42-
});
43-
44-
toast({
45-
description: (
46-
<p className="text-sm font-normal text-white">
47-
<span className="font-semibold">{file.name}</span> is too large.
48-
Max file size is 50MB.
49-
</p>
50-
),
51-
className: "bg-destructive",
52-
});
53-
continue;
54-
}
27+
const onDrop = useCallback((acceptedFiles: File[]) => {
28+
handleFileDrop(acceptedFiles).catch(console.error);
29+
}, []);
30+
31+
const handleFileDrop = async (acceptedFiles: File[]) => {
32+
console.log('Files dropped:', acceptedFiles.map(f => ({
33+
name: f.name,
34+
size: f.size,
35+
type: f.type,
36+
lastModified: f.lastModified
37+
})));
38+
39+
for (const file of acceptedFiles) {
40+
if (file.size > MAX_FILE_SIZE) {
41+
console.log('File too large:', {
42+
name: file.name,
43+
size: file.size,
44+
maxSize: MAX_FILE_SIZE
45+
});
5546

56-
setFiles((prev) => [...prev, file]);
57-
setUploadingFiles((prev) => new Set(prev).add(file.name));
47+
toast({
48+
description: (
49+
<p className="text-sm font-normal text-white">
50+
<span className="font-semibold">{file.name}</span> is too large.
51+
Max file size is 50MB.
52+
</p>
53+
),
54+
className: "bg-destructive",
55+
});
56+
continue;
57+
}
5858

59-
console.log('Starting upload for file:', {
60-
name: file.name,
61-
size: file.size,
62-
type: file.type,
63-
lastModified: file.lastModified
59+
setFiles((prev) => [...prev, file]);
60+
setUploadingFiles((prev) => new Set(prev).add(file.name));
61+
62+
console.log('Starting upload for file:', {
63+
name: file.name,
64+
size: file.size,
65+
type: file.type,
66+
lastModified: file.lastModified
67+
});
68+
69+
try {
70+
console.log('Calling uploadFile function with:', {
71+
fileName: file.name,
72+
fileType: file.type,
73+
ownerId,
74+
accountId,
75+
path
76+
});
77+
78+
const success = await uploadFile({
79+
file,
80+
ownerId,
81+
accountId,
82+
path: path || '/'
83+
});
84+
85+
console.log('Upload result:', {
86+
fileName: file.name,
87+
success,
88+
fileInfo: {
89+
size: file.size,
90+
type: file.type,
91+
lastModified: file.lastModified
92+
}
6493
});
94+
95+
if (!success) {
96+
throw new Error("Failed to upload file");
97+
}
6598

66-
try {
67-
console.log('Calling uploadFile function with:', {
68-
fileName: file.name,
69-
fileType: file.type,
70-
ownerId,
71-
accountId,
72-
path
73-
});
74-
75-
const success = await uploadFile({
76-
file,
77-
ownerId,
78-
accountId,
79-
path: path || '/'
80-
});
81-
82-
console.log('Upload result:', {
83-
fileName: file.name,
84-
success,
99+
toast({
100+
description: (
101+
<p className="text-sm font-normal text-white">
102+
<span className="font-semibold">{file.name}</span> uploaded successfully!
103+
</p>
104+
),
105+
className: "bg-green-500",
106+
});
107+
} catch (error: unknown) {
108+
let errorMessage = "Falha ao fazer upload do arquivo. Por favor, tente novamente.";
109+
110+
if (error instanceof Error) {
111+
console.error(`Error uploading ${file.name}:`, {
112+
message: error.message,
113+
stack: error.stack,
85114
fileInfo: {
86115
size: file.size,
87116
type: file.type,
88-
lastModified: file.lastModified
89-
}
90-
});
91-
92-
if (!success) {
93-
throw new Error("Failed to upload file");
94-
}
95-
96-
toast({
97-
description: (
98-
<p className="text-sm font-normal text-white">
99-
<span className="font-semibold">{file.name}</span> uploaded successfully!
100-
</p>
101-
),
102-
className: "bg-green-500",
117+
lastModified: file.lastModified,
118+
},
103119
});
104-
} catch (error: unknown) {
105-
let errorMessage = "Falha ao fazer upload do arquivo. Por favor, tente novamente.";
106-
107-
if (error instanceof Error) {
108-
console.error(`Error uploading ${file.name}:`, {
109-
message: error.message,
110-
stack: error.stack,
111-
fileInfo: {
112-
size: file.size,
113-
type: file.type,
114-
lastModified: file.lastModified,
115-
},
116-
});
117-
errorMessage = error.message;
118-
} else {
119-
console.error(`Unknown error uploading ${file.name}:`, {
120-
error,
121-
fileInfo: {
122-
size: file.size,
123-
type: file.type,
124-
lastModified: file.lastModified,
125-
},
126-
});
127-
}
128-
129-
toast({
130-
description: (
131-
<p className="text-sm font-normal text-white">
132-
{errorMessage}
133-
</p>
134-
),
135-
className: "bg-destructive",
136-
});
137-
} finally {
138-
console.log('Cleaning up file states:', file.name);
139-
setFiles((prevFiles) => prevFiles.filter((f) => f.name !== file.name));
140-
setUploadingFiles((prev) => {
141-
const newSet = new Set(prev);
142-
newSet.delete(file.name);
143-
return newSet;
120+
errorMessage = error.message;
121+
} else {
122+
console.error(`Unknown error uploading ${file.name}:`, {
123+
error,
124+
fileInfo: {
125+
size: file.size,
126+
type: file.type,
127+
lastModified: file.lastModified,
128+
},
144129
});
145130
}
131+
132+
toast({
133+
description: (
134+
<p className="text-sm font-normal text-white">
135+
{errorMessage}
136+
</p>
137+
),
138+
className: "bg-destructive",
139+
});
140+
} finally {
141+
console.log('Cleaning up file states:', file.name);
142+
setFiles((prevFiles) => prevFiles.filter((f) => f.name !== file.name));
143+
setUploadingFiles((prev) => {
144+
const newSet = new Set(prev);
145+
newSet.delete(file.name);
146+
return newSet;
147+
});
146148
}
147-
},
148-
[ownerId, accountId, path, toast]
149-
);
149+
}
150+
};
150151

151152
const { getRootProps, getInputProps } = useDropzone({
152153
onDrop,
153154
maxSize: MAX_FILE_SIZE,
154155
accept: {
155156
'image/*': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'],
156-
'video/*': ['.mp4', '.avi', '.mov', '.mkv', '.webm'],
157-
'audio/*': ['.mp3', '.wav', '.ogg', '.flac'],
157+
'video/*': ['.mp4', '.avi', '.mov', '.wmv'],
158+
'audio/*': ['.mp3', '.wav', '.ogg'],
158159
'application/pdf': ['.pdf'],
159160
'application/msword': ['.doc'],
160161
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
161-
'text/plain': ['.txt'],
162162
'application/vnd.ms-excel': ['.xls'],
163163
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
164-
'text/csv': ['.csv']
164+
'application/vnd.ms-powerpoint': ['.ppt'],
165+
'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'],
165166
}
166167
});
167168

0 commit comments

Comments
 (0)