Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
VCCI-News
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Văn Hoàng
VCCI-News
Commits
780033b0
Commit
780033b0
authored
May 15, 2026
by
Lê Bảo Hồng Đức
☄
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'fix/header' into 'develop-news'
fix header See merge request
!56
parents
67f22283
b6c2eab7
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
346 additions
and
190 deletions
+346
-190
index.tsx
src/app/(main)/(home)/components/featured-news/index.tsx
+3
-3
ArticlePage.tsx
src/app/(main)/[...slug]/templates/ArticlePage.tsx
+1
-1
header.tsx
src/app/(main)/_lib/layout/header.tsx
+141
-70
layout.tsx
src/app/(main)/layout.tsx
+1
-1
index.tsx
src/components/base/list-category/index.tsx
+2
-2
index.tsx
src/components/base/menu-category/index.tsx
+65
-70
index.tsx
src/components/base/menu-item/index.tsx
+99
-29
hover-card.tsx
src/components/ui/hover-card.tsx
+12
-10
_components.css
src/styles/_components.css
+22
-4
No files found.
src/app/(main)/(home)/components/featured-news/index.tsx
View file @
780033b0
...
@@ -57,7 +57,7 @@ function FeaturedNews() {
...
@@ -57,7 +57,7 @@ function FeaturedNews() {
{
primaryItem
.
categories
[
0
]?.
name
||
"Tin nổi bật"
}
{
primaryItem
.
categories
[
0
]?.
name
||
"Tin nổi bật"
}
</
span
>
</
span
>
<
h3
className=
"max-w-3xl text-[20px] font-bold leading-[1.28] text-white md:text-[28px] xl:text-[32px]"
>
<
h3
className=
"max-w-3xl
line-clamp-3
text-[20px] font-bold leading-[1.28] text-white md:text-[28px] xl:text-[32px]"
>
{
primaryItem
.
title
}
{
primaryItem
.
title
}
</
h3
>
</
h3
>
...
@@ -70,8 +70,8 @@ function FeaturedNews() {
...
@@ -70,8 +70,8 @@ function FeaturedNews() {
</
div
>
</
div
>
</
Link
>
</
Link
>
)
:
(
)
:
(
<
div
className=
"relative min-h-[260px] overflow-hidden rounded-
[24px]
bg-[#e9eef8] shadow-[0_18px_38px_rgba(28,52,120,0.12)] md:min-h-[320px] xl:min-h-[350px]"
>
<
div
className=
"relative min-h-[260px] overflow-hidden rounded-
3xl
bg-[#e9eef8] shadow-[0_18px_38px_rgba(28,52,120,0.12)] md:min-h-[320px] xl:min-h-[350px]"
>
<
div
className=
"flex h-full min-h-[260px] flex-col justify-end p-4 md:min-h-
[320px]
md:p-5 xl:min-h-[350px]"
>
<
div
className=
"flex h-full min-h-[260px] flex-col justify-end p-4 md:min-h-
80
md:p-5 xl:min-h-[350px]"
>
<
span
className=
"mb-2 h-8 w-28 rounded-[10px] bg-white/80"
/>
<
span
className=
"mb-2 h-8 w-28 rounded-[10px] bg-white/80"
/>
<
div
className=
"h-8 w-3/4 rounded bg-white/90 md:h-10"
/>
<
div
className=
"h-8 w-3/4 rounded bg-white/90 md:h-10"
/>
<
div
className=
"mt-2 h-5 w-28 rounded bg-white/70"
/>
<
div
className=
"mt-2 h-5 w-28 rounded bg-white/70"
/>
...
...
src/app/(main)/[...slug]/templates/ArticlePage.tsx
View file @
780033b0
...
@@ -93,7 +93,7 @@ export default function ArticlePage({ category, allCategories }: ArticlePageProp
...
@@ -93,7 +93,7 @@ export default function ArticlePage({ category, allCategories }: ArticlePageProp
{
categoryMenu
.
length
>
0
?
<
ListCategory
categories=
{
categoryMenu
}
/>
:
<
br
/>
}
{
categoryMenu
.
length
>
0
?
<
ListCategory
categories=
{
categoryMenu
}
/>
:
<
br
/>
}
<
div
className=
"grid grid-cols-1 lg:grid-cols-3 gap-6"
>
<
div
className=
"grid grid-cols-1 lg:grid-cols-3 gap-6"
>
<
main
className=
"lg:col-span-2 bg-
background
"
>
<
main
className=
"lg:col-span-2 bg-
white
"
>
<
div
className=
"pb-5 overflow-hidden"
>
<
div
className=
"pb-5 overflow-hidden"
>
{
paginatedPosts
.
length
?
(
{
paginatedPosts
.
length
?
(
paginatedPosts
.
map
((
item
)
=>
{
paginatedPosts
.
map
((
item
)
=>
{
...
...
src/app/(main)/_lib/layout/header.tsx
View file @
780033b0
This diff is collapsed.
Click to expand it.
src/app/(main)/layout.tsx
View file @
780033b0
...
@@ -9,7 +9,7 @@ export default function Layout({
...
@@ -9,7 +9,7 @@ export default function Layout({
children
:
React
.
ReactNode
;
children
:
React
.
ReactNode
;
}
>
)
{
}
>
)
{
return
(
return
(
<
main
className=
"flex flex-col min-h-screen bg-
background
"
>
<
main
className=
"flex flex-col min-h-screen bg-
white
"
>
<
Header
/>
<
Header
/>
<
div
className=
"flex-1"
>
{
children
}
</
div
>
<
div
className=
"flex-1"
>
{
children
}
</
div
>
<
ScrollToTopButton
/>
<
ScrollToTopButton
/>
...
...
src/components/base/list-category/index.tsx
View file @
780033b0
...
@@ -22,7 +22,7 @@ const ListCategory: React.FC<{ categories?: Category[] }> = ({ categories = [] }
...
@@ -22,7 +22,7 @@ const ListCategory: React.FC<{ categories?: Category[] }> = ({ categories = [] }
<
div
className=
"border-t border-gray-200 bg-white py-2"
>
<
div
className=
"border-t border-gray-200 bg-white py-2"
>
<
div
className=
"w-full px-4 sm:px-6 lg:px-8"
>
<
div
className=
"w-full px-4 sm:px-6 lg:px-8"
>
<
div
className=
"py-3"
>
<
div
className=
"py-3"
>
<
div
className=
"flex
flex-wrap items-center max-w-full overflow-x-auto
"
>
<
div
className=
"flex
max-w-full items-center gap-3 overflow-x-auto pb-1
"
>
{
categories
.
map
((
category
)
=>
{
{
categories
.
map
((
category
)
=>
{
const
href
=
resolveHref
(
category
);
const
href
=
resolveHref
(
category
);
const
menu
=
{
id
:
category
.
id
,
name
:
category
.
name
,
link
:
href
};
const
menu
=
{
id
:
category
.
id
,
name
:
category
.
name
,
link
:
href
};
...
@@ -30,7 +30,7 @@ const ListCategory: React.FC<{ categories?: Category[] }> = ({ categories = [] }
...
@@ -30,7 +30,7 @@ const ListCategory: React.FC<{ categories?: Category[] }> = ({ categories = [] }
return
(
return
(
<
div
key=
{
category
.
id
}
className=
"shrink-0"
>
<
div
key=
{
category
.
id
}
className=
"shrink-0"
>
<
MenuItem
menu=
{
menu
}
active=
{
active
}
/>
<
MenuItem
menu=
{
menu
}
active=
{
active
}
variant=
"secondary"
/>
</
div
>
</
div
>
);
);
})
}
})
}
...
...
src/components/base/menu-category/index.tsx
View file @
780033b0
'use client'
'use client'
type
Menu
=
{
type
Menu
=
{
id
:
string
|
number
id
:
string
|
number
name
:
string
name
:
string
...
@@ -7,19 +8,22 @@ type Menu = {
...
@@ -7,19 +8,22 @@ type Menu = {
}
}
import
{
buttonVariants
}
from
'@components/ui/button'
import
{
buttonVariants
}
from
'@components/ui/button'
import
{
HoverCard
,
HoverCardContent
,
HoverCardTrigger
}
from
'@components/ui/hover-card'
import
{
cn
}
from
'@lib/utils'
import
{
cn
}
from
'@lib/utils'
import
{
useCallback
,
useMemo
}
from
'react'
import
{
HoverCard
,
HoverCardTrigger
,
HoverCardContent
}
from
'@components/ui/hover-card'
import
{
cva
}
from
'class-variance-authority'
import
{
usePathname
}
from
'next/navigation'
import
Link
from
'next/link'
import
Link
from
'next/link'
import
{
usePathname
}
from
'next/navigation'
import
{
useCallback
,
useMemo
}
from
'react'
export
function
MenuItem
(
props
:
{
variant
?:
'main'
|
'secondary'
;
menu
:
Menu
;
active
?:
boolean
})
{
export
function
MenuItem
(
props
:
{
variant
?:
'main'
|
'secondary'
;
menu
:
Menu
;
active
?:
boolean
})
{
const
{
menu
,
variant
=
'main'
,
active
}
=
props
const
{
menu
,
variant
=
'main'
,
active
}
=
props
const
pathname
=
usePathname
()
const
pathname
=
usePathname
()
const
isActive
=
pathname
.
startsWith
(
menu
.
link
??
''
);
const
normalizedLink
=
menu
.
link
&&
menu
.
link
!==
'#'
?
menu
.
link
:
'/'
const
hasChildren
=
Boolean
(
menu
.
children
?.
length
)
const
isRoot
=
normalizedLink
===
'/'
const
isActive
=
active
||
(
isRoot
?
pathname
===
'/'
:
pathname
.
startsWith
(
normalizedLink
))
const
linkId
=
useMemo
(()
=>
`trigger_
${
menu
.
id
}
`
,
[
menu
.
id
])
const
linkId
=
useMemo
(()
=>
`trigger_
${
menu
.
id
}
`
,
[
menu
.
id
])
const
hoverCardRef
=
useCallback
(
const
hoverCardRef
=
useCallback
(
(
element
:
HTMLDivElement
)
=>
{
(
element
:
HTMLDivElement
)
=>
{
if
(
!
element
)
return
if
(
!
element
)
return
...
@@ -28,76 +32,67 @@ export function MenuItem(props: { variant?: 'main' | 'secondary'; menu: Menu; ac
...
@@ -28,76 +32,67 @@ export function MenuItem(props: { variant?: 'main' | 'secondary'; menu: Menu; ac
[linkId]
[linkId]
)
)
return (
const trigger = (
<HoverCard openDelay={0} closeDelay={0}>
<HoverCardTrigger asChild>
<Link
<Link
aria-selected={active ||
isActive}
aria-selected={
isActive}
id={linkId}
id={linkId}
target={(menu.link ?? '')
.startsWith('/') ? '_self' : '_blank'}
target={normalizedLink
.startsWith('/') ? '_self' : '_blank'}
href={menu.link ?? '/'
}
href={normalizedLink
}
className={menuItemTriggerVariant({ variant }
)}
className={menuItemTriggerClass(variant
)}
>
>
{menu.name}
<span className="relative z-10 truncate">{menu.name}</span>
{variant === 'main' ? <span className="menu-item-underline" aria-hidden="true" /> : null}
</Link>
</Link>
</HoverCardTrigger>
)
if (!hasChildren) {
return trigger
}
{menu.children && (
return (
<HoverCardContent ref={hoverCardRef} className={menuItemHoverBoxVariant({ variant })}>
<HoverCard openDelay={80} closeDelay={120}>
{menu.children.map((subMenu) => (
<HoverCardTrigger asChild>{trigger}</HoverCardTrigger>
<Link key={subMenu.id} href={subMenu.link ?? '/'} className={menuItemChildVariant({ variant })}>
<HoverCardContent ref={hoverCardRef} className={menuItemHoverBoxVariant(variant)}>
{menu.children?.map((subMenu) => (
<Link key={subMenu.id} href={subMenu.link ?? '/'} className={menuItemChildVariant(variant)}>
{subMenu.name}
{subMenu.name}
</Link>
</Link>
))}
))}
</HoverCardContent>
</HoverCardContent>
)}
</HoverCard>
</HoverCard>
)
)
}
}
const menuItemTriggerVariant = cva(
function menuItemTriggerClass(variant: 'main' | 'secondary') {
cn(buttonVariants({ variant: 'ghost' }), 'font-semibold focus-visible:ring-0 focus-visible:ring-offset-0 py-'),
if (variant === 'secondary') {
{
return cn(
variants: {
'inline-flex h-[36px] items-center justify-center rounded-full border border-[#d6dfeb] bg-white px-5 text-[13px] font-medium leading-none text-[#5f6b7d] shadow-none transition-colors duration-150',
variant: {
'hover:border-[#c5d2e3] hover:bg-[#f7faff] hover:text-[#1b5aa1]',
main: cn(
'aria-selected:border-[#16559d] aria-selected:bg-[#16559d] aria-selected:text-white',
'font-semibold text-[#363636] text-2xl hover:text-muted-foreground hover:bg-white py-3.5 px-5',
'focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0'
'aria-selected:text-muted-foreground'
),
secondary: cn(
'font-boldtext-primary border-t-2 border-t-transparent rounded-none',
'hover:text-primary/90',
'aria-selected:border-t-secondary aria-selected:bg-accent',
'aria-selected:bg-[#E9C826]'
)
)
}
}
},
defaultVariants: {
variant: 'main'
}
}
)
const menuItemHoverBoxVariant = cva('flex w-full flex-col gap-2 p-0', {
return cn(
variants: {
buttonVariants({ variant: 'ghost' }),
variant: {
'group relative inline-flex h-[60px] rounded-none border-b-2 border-transparent px-3 py-0 text-[15px] font-semibold text-slate-700 shadow-none transition-colors duration-150',
main: 'bg-secondary',
'hover:bg-transparent hover:text-[#2f57ff]',
secondary: 'bg-muted '
'aria-selected:bg-transparent aria-selected:text-[#2f57ff]',
}
'focus-visible:ring-0 focus-visible:ring-offset-0 xl:px-4'
},
)
defaultVariants: {
}
variant: 'main'
}
})
const menuItemChildVariant = cva(cn(buttonVariants({ variant: 'ghost' }), 'justify-start'), {
function menuItemHoverBoxVariant(variant: 'main' | 'secondary') {
variants: {
return cn(
variant: {
'mt-1 flex w-full min-w-[220px] flex-col gap-1 rounded-md border border-slate-200 bg-white p-2 shadow-[0_12px_30px_rgba(15,23,42,0.12)]',
main: 'text-secondary-foreground hover:text-muted-foreground hover:bg-secondary',
variant === 'secondary' ? 'bg-white' : ''
secondary: 'text-accent-foreground hover:text-primary/90 '
)
}
}
},
defaultVariants: {
function menuItemChildVariant(_variant: 'main' | 'secondary') {
variant: 'main'
return cn(
}
buttonVariants({ variant: 'ghost' }),
})
'h-10 justify-start rounded-md px-3 text-sm font-medium text-slate-600 transition-colors',
'hover:bg-slate-50 hover:text-[#2f57ff]'
)
}
src/components/base/menu-item/index.tsx
View file @
780033b0
import
{
usePathname
}
from
"next/navigation"
;
'use client'
import
Link
from
"next/link"
;
import
{
buttonVariants
}
from
'@components/ui/button'
import
{
HoverCard
,
HoverCardContent
,
HoverCardTrigger
}
from
'@components/ui/hover-card'
import
{
cn
}
from
'@lib/utils'
import
{
cva
}
from
'class-variance-authority'
import
Link
from
'next/link'
import
{
usePathname
}
from
'next/navigation'
import
{
useCallback
,
useMemo
}
from
'react'
type
MenuItemProps
=
{
type
MenuItemProps
=
{
title
:
string
;
title
:
string
link
?:
string
;
link
?:
string
items
:
{
title
:
string
;
link
:
string
}[]
;
items
:
{
title
:
string
;
link
:
string
}[]
}
;
}
const
MenuItem
=
({
title
,
link
,
items
}:
MenuItemProps
)
=>
{
const
MenuItem
=
({
title
,
link
,
items
}:
MenuItemProps
)
=>
{
const
pathname
=
usePathname
();
const
pathname
=
usePathname
()
const
isActive
=
!!
link
&&
(
pathname
===
link
||
(
link
!==
"/"
&&
pathname
.
startsWith
(
link
)));
const
normalizedLink
=
link
&&
link
!==
'#'
?
link
:
'/'
const
hasChildren
=
items
.
length
>
0
const
isRoot
=
normalizedLink
===
'/'
const
isActive
=
isRoot
?
pathname
===
'/'
:
pathname
===
normalizedLink
||
pathname
.
startsWith
(
normalizedLink
)
const
linkId
=
useMemo
(()
=>
`header-trigger-
${
title
}
`
,
[
title
])
return
(
const
hoverCardRef
=
useCallback
(
<
div
className=
"group relative"
>
(
element
:
HTMLDivElement
)
=>
{
if
(
!
element
)
return
const
triggerWidth
=
document
.
getElementById
(
linkId
)?.
offsetWidth
??
220
element
.
style
.
minWidth
=
`
${
Math
.
max
(
triggerWidth
,
320
)}
px`
element
.
style
.
maxWidth
=
'420px'
},
[
linkId
]
)
const
trigger
=
(
<
Link
<
Link
href=
{
link
??
"#"
}
id=
{
linkId
}
className=
{
`px-3 py-5 text-[16px] font-semibold transition block
href=
{
normalizedLink
}
${isActive ? "text-[#E8C518]" : "text-[#124588] hover:text-[#E8C518]"
}
aria
-
selected=
{
isActive
}
`
}
className=
{
menuItemTriggerVariant
()
}
>
>
{
title
}
<
span
className=
"relative z-10 whitespace-nowrap"
>
{
title
}
</
span
>
<
span
className=
{
`absolute bottom-[11px] left-1/2 h-[2px] -translate-x-1/2 rounded-full bg-[#2f57ff] transition-all duration-200 ${
isActive ? 'w-[44px]' : 'w-0 group-hover:w-[44px]'
}`
}
aria
-
hidden=
"true"
/>
</
Link
>
</
Link
>
)
if
(
!
hasChildren
)
{
return
<
div
className=
"relative shrink-0"
>
{
trigger
}
</
div
>
}
return
(
<
HoverCard
openDelay=
{
0
}
closeDelay=
{
90
}
>
<
HoverCardTrigger
asChild
>
{
trigger
}
</
HoverCardTrigger
>
<
HoverCardContent
ref=
{
hoverCardRef
}
align=
"start"
sideOffset=
{
0
}
className=
{
menuItemHoverBoxVariant
()
}
>
{
items
.
map
((
item
)
=>
{
const
isItemActive
=
pathname
===
item
.
link
{
/* Dropdown */
}
<
div
className=
"absolute left-0 top-full hidden group-hover:block bg-[#124588]/98 text-white text-[14px] font-medium min-w-[220px] shadow-lg"
>
{
items
.
map
((
item
,
i
)
=>
{
const
isItemActive
=
pathname
===
item
.
link
;
return
(
return
(
<
Link
<
Link
key=
{
i
}
key=
{
i
tem
.
link
}
href=
{
item
.
link
}
href=
{
item
.
link
}
className=
{
`block px-5 py-3 cursor-pointer whitespace-nowrap transition ${isItemActive ? "bg-[#e8c518]/80" : "hover:bg-[#e8c518]/80"
className=
{
menuItemChildVariant
({
active
:
isItemActive
})
}
}`
}
>
>
{
item
.
title
}
{
item
.
title
}
</
Link
>
</
Link
>
)
;
)
})
}
})
}
</
div
>
</
HoverCardContent
>
</
div
>
</
HoverCard
>
);
)
};
}
const
menuItemTriggerVariant
=
cva
(
cn
(
buttonVariants
({
variant
:
'ghost'
}),
'group relative inline-flex h-[58px] shrink-0 items-center whitespace-nowrap rounded-none bg-transparent px-[4px] py-0 text-[14px] font-semibold leading-none tracking-normal text-[#43506a] shadow-none transition'
,
'hover:bg-transparent hover:text-[#2f57ff]'
,
'aria-selected:bg-transparent aria-selected:text-[#2f57ff]'
,
'focus-visible:ring-0 focus-visible:ring-offset-0'
)
)
const
menuItemHoverBoxVariant
=
cva
(
'z-[80] flex w-auto flex-col gap-1 rounded-b-md rounded-t-none border border-slate-200 bg-white p-2 text-[13px] font-medium text-slate-600 shadow-[0_18px_36px_rgba(15,23,42,0.16)]'
)
const
menuItemChildVariant
=
cva
(
cn
(
buttonVariants
({
variant
:
'ghost'
}),
'h-auto min-h-10 justify-start rounded-md px-3 py-2.5 text-left text-sm font-medium leading-6 whitespace-normal break-words transition'
),
{
variants
:
{
active
:
{
true
:
'bg-[#eef3ff] text-[#2f57ff]'
,
false
:
'text-slate-600 hover:bg-[#eef3ff] hover:text-[#2f57ff]'
}
},
defaultVariants
:
{
active
:
false
}
}
)
export
default
MenuItem
;
export
default
MenuItem
src/components/ui/hover-card.tsx
View file @
780033b0
...
@@ -13,6 +13,7 @@ const HoverCardContent = React.forwardRef<
...
@@ -13,6 +13,7 @@ const HoverCardContent = React.forwardRef<
React
.
ElementRef
<
typeof
HoverCardPrimitive
.
Content
>
,
React
.
ElementRef
<
typeof
HoverCardPrimitive
.
Content
>
,
React
.
ComponentPropsWithoutRef
<
typeof
HoverCardPrimitive
.
Content
>
React
.
ComponentPropsWithoutRef
<
typeof
HoverCardPrimitive
.
Content
>
>
(({
className
,
align
=
"center"
,
sideOffset
=
4
,
...
props
},
ref
)
=>
(
>
(({
className
,
align
=
"center"
,
sideOffset
=
4
,
...
props
},
ref
)
=>
(
<
HoverCardPrimitive
.
Portal
>
<
HoverCardPrimitive
.
Content
<
HoverCardPrimitive
.
Content
ref=
{
ref
}
ref=
{
ref
}
align=
{
align
}
align=
{
align
}
...
@@ -23,6 +24,7 @@ const HoverCardContent = React.forwardRef<
...
@@ -23,6 +24,7 @@ const HoverCardContent = React.forwardRef<
)
}
)
}
{
...
props
}
{
...
props
}
/>
/>
</
HoverCardPrimitive
.
Portal
>
))
))
HoverCardContent
.
displayName
=
HoverCardPrimitive
.
Content
.
displayName
HoverCardContent
.
displayName
=
HoverCardPrimitive
.
Content
.
displayName
...
...
src/styles/_components.css
View file @
780033b0
...
@@ -13,6 +13,24 @@
...
@@ -13,6 +13,24 @@
@apply
fixed
top-0
right-0
left-0;
@apply
fixed
top-0
right-0
left-0;
}
}
.header-menu-scroll
{
-ms-overflow-style
:
none
;
scrollbar-width
:
none
;
}
.header-menu-scroll
::-webkit-scrollbar
{
display
:
none
;
}
.menu-item-underline
{
@apply
absolute
bottom-0
left-1/2
h-[2px]
w-0
-translate-x-1/2
rounded-full
bg-[#2f57ff]
transition-all
duration-200;
}
[
aria-selected
=
"true"
]
>
.menu-item-underline
,
a
:hover
>
.menu-item-underline
{
@apply
w-[44px];
}
/* Scrollbar */
/* Scrollbar */
.scrollbar
{
.scrollbar
{
scrollbar-color
:
rgba
(
6
,
62
,
142
,
0.38
)
rgba
(
219
,
232
,
255
,
0.38
);
scrollbar-color
:
rgba
(
6
,
62
,
142
,
0.38
)
rgba
(
219
,
232
,
255
,
0.38
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment