-
Notifications
You must be signed in to change notification settings - Fork 0
Chore: replace the mock into API #244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,4 @@ dist-ssr | |
*.sln | ||
*.sw? | ||
|
||
./.husky/_ | ||
|
||
.env | ||
./.husky/_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,46 @@ export default tseslint.config({ | |
}, | ||
}) | ||
``` | ||
--- | ||
|
||
## Tailwind CSS version lock (v3.3.5 fixed) | ||
|
||
> ⚠️ **Important:** This project uses **Tailwind CSS v3.3.5**. | ||
Do not upgrade to Tailwind v4. Doing so will cause PostCSS plugin errors and break the build. | ||
|
||
### Why? | ||
|
||
Tailwind v4 separates its PostCSS plugin into `@tailwindcss/postcss`, which is **incompatible** with the current `postcss.config.js`. | ||
|
||
If you see the following error: | ||
|
||
``` | ||
[plugin:vite:css] [postcss] It looks like you're trying to use tailwindcss directly as a PostCSS plugin... | ||
``` | ||
|
||
you’re accidentally using v4. | ||
|
||
### How to fix: | ||
|
||
1. Uninstall all Tailwind packages: | ||
|
||
```bash | ||
npm uninstall tailwindcss @tailwindcss/postcss @tailwindcss/node | ||
``` | ||
|
||
2. Reinstall Tailwind v3.3.5: | ||
|
||
```bash | ||
npm install [email protected] | ||
``` | ||
|
||
3. Set your postcss.config.js to use the Tailwind plugin: | ||
|
||
```js | ||
module.exports = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
}; | ||
``` |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -36,7 +36,7 @@ | |||||
"globals": "^15.15.0", | ||||||
"husky": "^9.1.7", | ||||||
"lint-staged": "^15.5.1", | ||||||
"postcss": "^8.5.6", | ||||||
"postcss": "^8.5.3", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PostCSS version was downgraded from ^8.5.6 to ^8.5.3. This change appears unrelated to the mock implementation purpose and may introduce compatibility issues.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
"prettier": "^3.5.3", | ||||||
"tailwindcss": "^3.3.5", | ||||||
"typescript": "~5.7.2", | ||||||
|
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||
import { useState } from 'react'; | ||||||
import { useForm, useFieldArray } from 'react-hook-form'; | ||||||
import { useForm } from 'react-hook-form'; | ||||||
import { zodResolver } from '@hookform/resolvers/zod'; | ||||||
import { registrationSchema } from '../../../hooks/validation/register'; | ||||||
import { RegistrationFormValues, registrationSchema } from '../../../hooks/validation/register'; | ||||||
import TextInput from '../../ui/TextInput'; | ||||||
import EmailInput from '../../ui/EmailInput'; | ||||||
import PasswordInput from '../../ui/PasswordInput'; | ||||||
|
@@ -10,33 +10,15 @@ import { registerUser } from '../../../lib/register'; | |||||
import { messages } from '../../../lib/messages'; | ||||||
import Spinner from '../../ui/Spinner'; | ||||||
import { useNavigate } from 'react-router-dom'; | ||||||
import { RegistrationFormValues } from '../../../hooks/validation/register'; | ||||||
|
||||||
const RegistrationForm: React.FC = () => { | ||||||
const navigate = useNavigate(); | ||||||
const { | ||||||
register, | ||||||
handleSubmit, | ||||||
formState: { errors }, | ||||||
watch, | ||||||
control, | ||||||
} = useForm<RegistrationFormValues>({ | ||||||
resolver: zodResolver(registrationSchema), | ||||||
defaultValues: { | ||||||
first_name: '', | ||||||
last_name: '', | ||||||
email: '', | ||||||
password: '', | ||||||
bio: null, | ||||||
location: null, | ||||||
skills: [], | ||||||
profile_image: null, | ||||||
}, | ||||||
}); | ||||||
|
||||||
const { fields, append, remove } = useFieldArray({ | ||||||
control, | ||||||
name: 'skills', | ||||||
}); | ||||||
|
||||||
const [loading, setLoading] = useState(false); | ||||||
|
@@ -49,30 +31,9 @@ const RegistrationForm: React.FC = () => { | |||||
setErrorMsg(''); | ||||||
|
||||||
try { | ||||||
const formData = new FormData(); | ||||||
|
||||||
const fileInput = watch('profile_image'); | ||||||
const fileList = fileInput instanceof FileList ? fileInput : null; | ||||||
|
||||||
const profileImageFile = fileList?.[0]; | ||||||
const parsedSkills = Array.isArray(data.skills) ? data.skills : []; | ||||||
|
||||||
formData.append('first_name', data.first_name || ''); | ||||||
formData.append('last_name', data.last_name || ''); | ||||||
formData.append('email', data.email || ''); | ||||||
formData.append('password', data.password || ''); | ||||||
formData.append('bio', data.bio ?? ''); | ||||||
formData.append('location', data.location ?? ''); | ||||||
formData.append('skills', JSON.stringify(parsedSkills)); | ||||||
|
||||||
if (profileImageFile) { | ||||||
formData.append('profile_image', profileImageFile); | ||||||
} | ||||||
|
||||||
|
||||||
await registerUser(formData); | ||||||
|
||||||
await registerUser(data); | ||||||
setSuccessMsg(messages.success.register.user.success); | ||||||
|
||||||
navigate('/dashboard'); | ||||||
} catch { | ||||||
setErrorMsg(messages.error.register.user.default); | ||||||
|
@@ -88,17 +49,17 @@ const RegistrationForm: React.FC = () => { | |||||
> | ||||||
<TextInput | ||||||
label="First Name" | ||||||
{...register('first_name')} | ||||||
{...register('firstName')} | ||||||
placeholder="e.g. Taro" | ||||||
error={errors.first_name?.message} | ||||||
error={errors.firstName?.message} | ||||||
className="w-full" | ||||||
/> | ||||||
|
||||||
<TextInput | ||||||
label="Last Name" | ||||||
{...register('last_name')} | ||||||
{...register('lastName')} | ||||||
placeholder="e.g. Yamada" | ||||||
error={errors.last_name?.message} | ||||||
error={errors.lastName?.message} | ||||||
className="w-full" | ||||||
/> | ||||||
|
||||||
|
@@ -113,69 +74,16 @@ const RegistrationForm: React.FC = () => { | |||||
<PasswordInput | ||||||
label="Password" | ||||||
{...register('password')} | ||||||
placeholder="Minimum 8 characters" | ||||||
placeholder="Minimum 6 characters" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Password placeholder states 'Minimum 6 characters' but the validation schema requires minimum 8 characters. This inconsistency will confuse users.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
error={errors.password?.message} | ||||||
className="w-full mb-5 mt-10" | ||||||
/> | ||||||
|
||||||
<label className="font-medium text-sm text-gray-700">Gender (optional)</label> | ||||||
<select {...register('bio')} className="w-full border rounded p-2"> | ||||||
<option value="">Prefer not to say</option> | ||||||
<option value="man">Man</option> | ||||||
<option value="woman">Woman</option> | ||||||
<option value="nonbinary">Non-binary</option> | ||||||
<option value="other">Other</option> | ||||||
</select> | ||||||
|
||||||
<TextInput | ||||||
label="Location" | ||||||
{...register('location')} | ||||||
placeholder="Where are you based?" | ||||||
error={errors.location?.message} | ||||||
className="w-full" | ||||||
/> | ||||||
|
||||||
<label className="text-sm font-medium text-gray-700">Skills</label> | ||||||
{fields.map((field, index) => ( | ||||||
<div key={field.id} className="flex items-center gap-2"> | ||||||
<TextInput | ||||||
{...register(`skills.${index}`)} | ||||||
placeholder={`Skill ${index + 1}`} | ||||||
error={errors.skills?.[index]?.message} | ||||||
className="w-full" | ||||||
/> | ||||||
{fields.length > 1 && ( | ||||||
<button | ||||||
type="button" | ||||||
onClick={() => remove(index)} | ||||||
className="text-red-500 text-sm hover:underline" | ||||||
> | ||||||
delete | ||||||
</button> | ||||||
)} | ||||||
</div> | ||||||
))} | ||||||
|
||||||
<button | ||||||
type="button" | ||||||
onClick={() => append('')} | ||||||
className="text-indigo-600 text-sm hover:underline mt-1 self-start" | ||||||
> | ||||||
+ add your skill | ||||||
</button> | ||||||
|
||||||
<input | ||||||
type="file" | ||||||
accept="image/*" | ||||||
{...register('profile_image')} | ||||||
className="w-full border rounded p-2" | ||||||
/> | ||||||
|
||||||
<div className="mt-10"> | ||||||
<Button type="submit" className="w-full" disabled={loading}> | ||||||
{loading ? ( | ||||||
<div className="flex items-center justify-center gap-2"> | ||||||
<Spinner size="sm"/> Submitting... | ||||||
<Spinner size="sm" /> Submitting... | ||||||
</div> | ||||||
) : ( | ||||||
'Register' | ||||||
|
@@ -193,6 +101,7 @@ const RegistrationForm: React.FC = () => { | |||||
{errorMsg} | ||||||
</p> | ||||||
)} | ||||||
|
||||||
</form> | ||||||
); | ||||||
}; | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +0,0 @@ | ||
export const API_BASE_URL = import.meta.env.VITE_API_BASE_URL; | ||
|
||
export const API_ENDPOINTS = { | ||
users: { | ||
register: `${API_BASE_URL}/users/register`, | ||
list: `${API_BASE_URL}/users`, | ||
detail: (id: string) => `${API_BASE_URL}/users/${id}`, | ||
create: `${API_BASE_URL}/users`, | ||
update: (id: string) => `${API_BASE_URL}/users/${id}`, | ||
delete: (id: string) => `${API_BASE_URL}/users/${id}`, | ||
}, | ||
auth: { | ||
login: `${API_BASE_URL}/auth/login`, | ||
logout: `${API_BASE_URL}/auth/logout`, | ||
me: `${API_BASE_URL}/auth/me`, | ||
}, | ||
}; | ||
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,15 +1,12 @@ | ||||||
import React, { useState } from 'react'; | ||||||
import { useForm } from 'react-hook-form'; | ||||||
import { useNavigate } from "react-router-dom"; | ||||||
import { zodResolver } from '@hookform/resolvers/zod'; | ||||||
import { loginSchema, LoginFormValues } from '../../../hooks/validation/login'; | ||||||
import { loginUser } from '../../../lib/login'; | ||||||
import LoginForm from '../../../components/forms/login-form/LoginForm'; | ||||||
import { messages } from "../../../lib/messages"; | ||||||
import { User, fetchUserProfile } from "../../../lib/user"; | ||||||
import {messages} from "../../../lib/messages"; | ||||||
|
||||||
const LoginContainer: React.FC = () => { | ||||||
const navigate = useNavigate(); | ||||||
const { | ||||||
register, | ||||||
handleSubmit, | ||||||
|
@@ -27,21 +24,7 @@ const LoginContainer: React.FC = () => { | |||||
|
||||||
try { | ||||||
const response = await loginUser(data); | ||||||
const payload = response.data; | ||||||
|
||||||
if (response.status === 'success' && payload.user) { | ||||||
const user = payload.user; | ||||||
|
||||||
localStorage.setItem('userId', user.id.toString()); | ||||||
localStorage.setItem('token', user.token || ''); | ||||||
|
||||||
const userProfile: User = await fetchUserProfile(user.id.toString(), user.token || ''); | ||||||
|
||||||
navigate('/dashboard'); | ||||||
|
||||||
} | ||||||
|
||||||
setErrorMsg(messages.error.login.default); | ||||||
console.log(response); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Console.log statement should be removed from production code. Consider using proper logging or removing this debug statement.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
} catch (error) { | ||||||
setErrorMsg(messages.error.login.default); | ||||||
} finally { | ||||||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Port mapping inconsistency: The container is mapped to port 5174, but vite.config.ts specifies port 5173. This will cause the application to be unreachable.
Copilot uses AI. Check for mistakes.